diff --git a/BotSharp.sln b/BotSharp.sln
index 0cf4325e..c6d0684b 100644
--- a/BotSharp.sln
+++ b/BotSharp.sln
@@ -75,7 +75,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.ChatHub", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.TelegramBots", "src\Plugins\BotSharp.Plugin.TelegramBots\BotSharp.Plugin.TelegramBots.csproj", "{DCA18996-4D3A-4E98-BCD0-1FB77C59253E}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Logger", "src\Infrastructure\BotSharp.Logger\BotSharp.Logger.csproj", "{5CA3335E-E6AD-46FD-B277-29BBC3A16500}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Logger", "src\Infrastructure\BotSharp.Logger\BotSharp.Logger.csproj", "{5CA3335E-E6AD-46FD-B277-29BBC3A16500}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.Selenium.csproj b/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.Selenium.csproj
new file mode 100644
index 00000000..20ca5175
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.Selenium.csproj
@@ -0,0 +1,13 @@
+
+
+
+ netstandard2.1
+ enable
+ $(MSBuildProjectName.Replace(" ", "_"))s
+
+
+
+
+
+
+
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj b/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj
index 480ebabc..b5c7afe8 100644
--- a/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/BotSharp.Plugin.WebDriver.csproj
@@ -1,4 +1,4 @@
-
+
netstandard2.1
@@ -10,7 +10,21 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightInstance.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightInstance.cs
new file mode 100644
index 00000000..41faa4c5
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightInstance.cs
@@ -0,0 +1,21 @@
+namespace BotSharp.Plugin.WebDriver.Drivers;
+
+public class PlaywrightInstance : IDisposable
+{
+ IPlaywright _playwright;
+ IBrowser _browser;
+ IPage _page;
+
+ public IPlaywright Playwright => _playwright;
+ public IBrowser Browser => _browser;
+ public IPage Page => _page;
+
+ public void SetPlaywright(IPlaywright playwright) { _playwright = playwright; }
+ public void SetBrowser(IBrowser browser) { _browser = browser; }
+ public void SetPage(IPage page) { _page = page; }
+
+ public void Dispose()
+ {
+ _playwright.Dispose();
+ }
+}
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightWebDriver.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightWebDriver.cs
new file mode 100644
index 00000000..15a3673f
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightWebDriver.cs
@@ -0,0 +1,76 @@
+using BotSharp.Plugin.WebDriver.Services;
+
+namespace BotSharp.Plugin.WebDriver.Drivers;
+
+public class PlaywrightWebDriver
+{
+ private readonly IServiceProvider _services;
+ private readonly PlaywrightInstance _instance;
+
+ public PlaywrightWebDriver(IServiceProvider services, PlaywrightInstance instance)
+ {
+ _services = services;
+ _instance = instance;
+ }
+
+ public async Task LaunchBrowser(string? url)
+ {
+ if (_instance.Playwright == null)
+ {
+ var playwright = await Playwright.CreateAsync();
+ _instance.SetPlaywright(playwright);
+ }
+
+ if (_instance.Browser == null)
+ {
+ var browser = await _instance.Playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
+ {
+ Headless = false,
+ Channel = "chrome",
+ });
+ _instance.SetBrowser(browser);
+ }
+
+ if (!string.IsNullOrEmpty(url))
+ {
+ var page = await _instance.Browser.NewPageAsync();
+ _instance.SetPage(page);
+ var response = await page.GotoAsync(url);
+ }
+
+ return _instance.Browser;
+ }
+
+ public async Task ClickElement(Agent agent, BrowsingContextIn context, string messageId)
+ {
+ // Retrieve the page raw html and infer the element path
+ var body = await _instance.Page.QuerySelectorAsync("body");
+
+ var str = new List();
+ var anchors = await body.QuerySelectorAllAsync("a");
+ foreach (var a in anchors)
+ {
+ var text = await a.TextContentAsync();
+ if (!string.IsNullOrEmpty(text))
+ {
+ str.Add($"{text}");
+ }
+ }
+
+ var buttons = await body.QuerySelectorAllAsync("button");
+ foreach (var btn in buttons)
+ {
+ var text = await btn.TextContentAsync();
+ if (!string.IsNullOrEmpty(text))
+ {
+ str.Add($"");
+ }
+ }
+
+ var driverService = _services.GetRequiredService();
+ var htmlElementContextOut = await driverService.FindElement(agent, string.Join("", str), context.ElementName, messageId);
+
+ var element = _instance.Page.Locator(htmlElementContextOut.TagName).Nth(htmlElementContextOut.Index + 1);
+ await element.ClickAsync();
+ }
+}
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Functions/ClickHtmlElementFn.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Functions/ClickHtmlElementFn.cs
new file mode 100644
index 00000000..4b3d7a07
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/Functions/ClickHtmlElementFn.cs
@@ -0,0 +1,31 @@
+using BotSharp.Abstraction.Agents;
+
+namespace BotSharp.Plugin.WebDriver.Functions;
+
+public class ClickHtmlElementFn : IFunctionCallback
+{
+ public string Name => "click_html_element";
+
+ private readonly IServiceProvider _services;
+ private readonly PlaywrightWebDriver _driver;
+
+ public ClickHtmlElementFn(IServiceProvider services,
+ PlaywrightWebDriver driver)
+ {
+ _services = services;
+ _driver = driver;
+ }
+
+ public async Task Execute(RoleDialogModel message)
+ {
+ var args = JsonSerializer.Deserialize(message.FunctionArgs);
+
+ var agentService = _services.GetRequiredService();
+ var agent = await agentService.LoadAgent(message.CurrentAgentId);
+ await _driver.ClickElement(agent, args, message.MessageId);
+
+ message.Content = "Executed successfully.";
+
+ return true;
+ }
+}
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Functions/OpenBrowserFn.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Functions/OpenBrowserFn.cs
new file mode 100644
index 00000000..0d18e640
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/Functions/OpenBrowserFn.cs
@@ -0,0 +1,28 @@
+using BotSharp.Plugin.WebDriver.LlmContexts;
+
+namespace BotSharp.Plugin.WebDriver.Functions;
+
+public class OpenBrowserFn : IFunctionCallback
+{
+ public string Name => "open_browser";
+
+ private readonly IServiceProvider _services;
+ private readonly PlaywrightWebDriver _driver;
+
+ public OpenBrowserFn(IServiceProvider services,
+ PlaywrightWebDriver driver)
+ {
+ _services = services;
+ _driver = driver;
+ }
+
+ public async Task Execute(RoleDialogModel message)
+ {
+ var args = JsonSerializer.Deserialize(message.FunctionArgs);
+
+ var browser = await _driver.LaunchBrowser(args.Url);
+ message.Content = "Executed successfully.";
+
+ return true;
+ }
+}
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/LlmContexts/BrowsingContextIn.cs b/src/Plugins/BotSharp.Plugin.WebDriver/LlmContexts/BrowsingContextIn.cs
new file mode 100644
index 00000000..401b8e61
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/LlmContexts/BrowsingContextIn.cs
@@ -0,0 +1,15 @@
+using System.Text.Json.Serialization;
+
+namespace BotSharp.Plugin.WebDriver.LlmContexts;
+
+public class BrowsingContextIn
+{
+ [JsonPropertyName("url")]
+ public string? Url { get; set; }
+
+ [JsonPropertyName("element_name")]
+ public string? ElementName { get; set; }
+
+ [JsonPropertyName("input_text")]
+ public string? InputText { get; set; }
+}
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/LlmContexts/HtmlElementContextOut.cs b/src/Plugins/BotSharp.Plugin.WebDriver/LlmContexts/HtmlElementContextOut.cs
new file mode 100644
index 00000000..a325a4f6
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/LlmContexts/HtmlElementContextOut.cs
@@ -0,0 +1,12 @@
+using System.Text.Json.Serialization;
+
+namespace BotSharp.Plugin.WebDriver.LlmContexts;
+
+public class HtmlElementContextOut
+{
+ [JsonPropertyName("tag_name")]
+ public string TagName { get; set; }
+
+ [JsonPropertyName("index")]
+ public int Index { get; set; }
+}
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/README.md b/src/Plugins/BotSharp.Plugin.WebDriver/README.md
new file mode 100644
index 00000000..6cdb6a90
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/README.md
@@ -0,0 +1,10 @@
+# Web Driver
+
+The WebDriver project will provide a new agent of `Web Browser` plugged into BotSharp's Routing mechanism.
+When Router analyzes that the user's intention is to operate the web page, it will be routed to this Agent.
+This Agent will contain some predefined action functions.
+After analyzing the user's conversation record, it will generate the corresponding execution function and then call the browsers' API to perform corresponding operations.
+
+## Installation
+
+1. Copy `agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b` folder to `WebStarter\data\agents`
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Services/WebDriverService.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Services/WebDriverService.cs
new file mode 100644
index 00000000..913f9156
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/Services/WebDriverService.cs
@@ -0,0 +1,56 @@
+using BotSharp.Abstraction.Agents.Enums;
+using BotSharp.Abstraction.MLTasks;
+using BotSharp.Core.Infrastructures;
+
+namespace BotSharp.Plugin.WebDriver.Services;
+
+public class WebDriverService
+{
+ private readonly IServiceProvider _services;
+
+ public WebDriverService(IServiceProvider services)
+ {
+ _services = services;
+ }
+
+ public async Task FindElement(Agent agent, string html, string elementName, string messageId)
+ {
+ var parserInstruction = agent.Templates.First(x => x.Name == "html_parser").Content;
+
+ var render = _services.GetRequiredService();
+ var prompt = render.Render(parserInstruction, new Dictionary
+ {
+ { "html_content", html },
+ { "element_name", elementName }
+ });
+
+ var completer = CompletionProvider.GetCompletion(_services,
+ agentConfig: agent.LlmConfig);
+
+ if (completer is ITextCompletion textCompleter)
+ {
+ var result = await textCompleter.GetCompletion(prompt, agent.Id, messageId);
+ return result.JsonContent();
+ }
+ else if (completer is IChatCompletion chatCompleter)
+ {
+ var dialogs = new List
+ {
+ new RoleDialogModel(AgentRole.User, prompt)
+ {
+ CurrentAgentId = agent.Id,
+ MessageId = messageId
+ }
+ };
+ var result = chatCompleter.GetChatCompletions(new Agent
+ {
+ Id = agent.Id,
+ Name = agent.Name,
+ Instruction = "You're a HTML Parser."
+ }, dialogs);
+ return result.Content.JsonContent();
+ }
+
+ return null;
+ }
+}
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Using.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Using.cs
new file mode 100644
index 00000000..ca78d12b
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/Using.cs
@@ -0,0 +1,17 @@
+global using System;
+global using System.Collections.Generic;
+global using System.Text;
+global using BotSharp.Abstraction.Conversations;
+global using BotSharp.Abstraction.Plugins;
+global using System.Text.Json;
+global using BotSharp.Abstraction.Conversations.Models;
+global using Microsoft.Playwright;
+global using BotSharp.Plugin.WebDriver.Drivers;
+global using System.Threading.Tasks;
+global using BotSharp.Abstraction.Functions;
+global using BotSharp.Abstraction.Agents.Models;
+global using BotSharp.Abstraction.Templating;
+global using BotSharp.Plugin.WebDriver.LlmContexts;
+global using Microsoft.Extensions.DependencyInjection;
+global using System.Linq;
+global using BotSharp.Abstraction.Utilities;
\ No newline at end of file
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/WebDriverPlugin.cs b/src/Plugins/BotSharp.Plugin.WebDriver/WebDriverPlugin.cs
index 5dde8be6..c83533f6 100644
--- a/src/Plugins/BotSharp.Plugin.WebDriver/WebDriverPlugin.cs
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/WebDriverPlugin.cs
@@ -1,14 +1,17 @@
-using BotSharp.Abstraction.Plugins;
+using BotSharp.Plugin.WebDriver.Services;
using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-namespace BotSharp.Plugin.WebDriver;
+namespace BotSharp.Plugin.Playwrights;
public class WebDriverPlugin : IBotSharpPlugin
{
public string Name => "Web Driver";
+ public string Description => "Manipulate web browser in automation tools.";
+
public void RegisterDI(IServiceCollection services, IConfiguration config)
{
-
+ services.AddScoped();
+ services.AddSingleton();
+ services.AddScoped();
}
}
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/agent.json b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/agent.json
new file mode 100644
index 00000000..d733511b
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/agent.json
@@ -0,0 +1,9 @@
+{
+ "name": "Web Browser",
+ "description": "Perform a specific action on a web browser",
+ "createdDateTime": "2024-01-02T00:00:00Z",
+ "updatedDateTime": "2024-01-02T00:00:00Z",
+ "id": "f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b",
+ "allowRouting": true,
+ "isPublic": true
+ }
\ No newline at end of file
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/functions.json b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/functions.json
new file mode 100644
index 00000000..b406814f
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/functions.json
@@ -0,0 +1,30 @@
+[
+ {
+ "name": "open_browser",
+ "description": "open a browser",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "url": {
+ "type": "string",
+ "description": "website url."
+ }
+ },
+ "required": []
+ }
+ },
+ {
+ "name": "click_html_element",
+ "description": "Click the html element in a web page.",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "element_name": {
+ "type": "string",
+ "description": "the html element name."
+ }
+ },
+ "required": ["element_name"]
+ }
+ }
+]
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/instruction.liquid b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/instruction.liquid
new file mode 100644
index 00000000..1f9f0377
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/instruction.liquid
@@ -0,0 +1,2 @@
+You are a web browser that can manipulate web elements through automated tools like Playwright and Selenium.
+
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/templates/html_parser.liquid b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/templates/html_parser.liquid
new file mode 100644
index 00000000..0b0d7e44
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/agents/f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b/templates/html_parser.liquid
@@ -0,0 +1,6 @@
+{{ html_content }}
+
+=== According to above HTML ===
+You're using Playwright selector syntax.
+Find the html element CSS selector full path of "{{ element_name }}".
+Output in JSON format {"tag_name": "", "index": -1} with appropriate values.
\ No newline at end of file
diff --git a/src/WebStarter/WebStarter.csproj b/src/WebStarter/WebStarter.csproj
index 1f011ef6..d7e6168f 100644
--- a/src/WebStarter/WebStarter.csproj
+++ b/src/WebStarter/WebStarter.csproj
@@ -61,12 +61,13 @@
+
+
+
-
-
diff --git a/src/WebStarter/appsettings.json b/src/WebStarter/appsettings.json
index 345aabab..ba36ef8b 100644
--- a/src/WebStarter/appsettings.json
+++ b/src/WebStarter/appsettings.json
@@ -167,6 +167,7 @@
"BotSharp.Plugin.WeChat",
// "BotSharp.Plugin.TelegramBots",
// "BotSharp.Plugin.RoutingSpeeder",
+ "BotSharp.Plugin.WebDriver",
"BotSharp.Plugin.PizzaBot"
]
}
diff --git a/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/agent.json b/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/agent.json
index 0394958a..d3756375 100644
--- a/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/agent.json
+++ b/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/agent.json
@@ -1,7 +1,7 @@
{
"name": "PizzaBot",
"description": "Pizza restaurant AI Bot",
- "createdDateTime": "2023-08-18T14:39:32.2349685Z",
+ "createdDateTime": "2023-08-18T10:39:32.2349685Z",
"updatedDateTime": "2023-08-18T14:39:32.2349686Z",
"id": "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a",
"iconUrl": "https://cdn.iconscout.com/icon/premium/png-256-thumb/route-1613278-1368497.png",
diff --git a/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj b/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj
index ac6d48a2..5c2cee0e 100644
--- a/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj
+++ b/tests/BotSharp.Plugin.PizzaBot/BotSharp.Plugin.PizzaBot.csproj
@@ -1,4 +1,4 @@
-
+
netstandard2.1
@@ -13,6 +13,12 @@
+
+
+
+
+
+
diff --git a/src/WebStarter/data/agents/b284db86-e9c2-4c25-a59e-4649797dd130/agent.json b/tests/BotSharp.Plugin.PizzaBot/agents/b284db86-e9c2-4c25-a59e-4649797dd130/agent.json
similarity index 100%
rename from src/WebStarter/data/agents/b284db86-e9c2-4c25-a59e-4649797dd130/agent.json
rename to tests/BotSharp.Plugin.PizzaBot/agents/b284db86-e9c2-4c25-a59e-4649797dd130/agent.json
diff --git a/src/WebStarter/data/agents/b284db86-e9c2-4c25-a59e-4649797dd130/functions.json b/tests/BotSharp.Plugin.PizzaBot/agents/b284db86-e9c2-4c25-a59e-4649797dd130/functions.json
similarity index 100%
rename from src/WebStarter/data/agents/b284db86-e9c2-4c25-a59e-4649797dd130/functions.json
rename to tests/BotSharp.Plugin.PizzaBot/agents/b284db86-e9c2-4c25-a59e-4649797dd130/functions.json
diff --git a/src/WebStarter/data/agents/b284db86-e9c2-4c25-a59e-4649797dd130/instruction.liquid b/tests/BotSharp.Plugin.PizzaBot/agents/b284db86-e9c2-4c25-a59e-4649797dd130/instruction.liquid
similarity index 100%
rename from src/WebStarter/data/agents/b284db86-e9c2-4c25-a59e-4649797dd130/instruction.liquid
rename to tests/BotSharp.Plugin.PizzaBot/agents/b284db86-e9c2-4c25-a59e-4649797dd130/instruction.liquid
diff --git a/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json b/tests/BotSharp.Plugin.PizzaBot/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json
similarity index 100%
rename from src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json
rename to tests/BotSharp.Plugin.PizzaBot/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json
diff --git a/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/functions.json b/tests/BotSharp.Plugin.PizzaBot/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/functions.json
similarity index 100%
rename from src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/functions.json
rename to tests/BotSharp.Plugin.PizzaBot/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/functions.json
diff --git a/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/instruction.liquid b/tests/BotSharp.Plugin.PizzaBot/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/instruction.liquid
similarity index 100%
rename from src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/instruction.liquid
rename to tests/BotSharp.Plugin.PizzaBot/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/instruction.liquid
diff --git a/src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/responses/func.get_pizza_price.0.liquid b/tests/BotSharp.Plugin.PizzaBot/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/responses/func.get_pizza_price.0.liquid
similarity index 100%
rename from src/WebStarter/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/responses/func.get_pizza_price.0.liquid
rename to tests/BotSharp.Plugin.PizzaBot/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/responses/func.get_pizza_price.0.liquid
diff --git a/src/WebStarter/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/agent.json b/tests/BotSharp.Plugin.PizzaBot/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/agent.json
similarity index 100%
rename from src/WebStarter/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/agent.json
rename to tests/BotSharp.Plugin.PizzaBot/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/agent.json
diff --git a/src/WebStarter/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/instruction.liquid b/tests/BotSharp.Plugin.PizzaBot/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/instruction.liquid
similarity index 100%
rename from src/WebStarter/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/instruction.liquid
rename to tests/BotSharp.Plugin.PizzaBot/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/instruction.liquid
diff --git a/src/WebStarter/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.executor.liquid b/tests/BotSharp.Plugin.PizzaBot/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.executor.liquid
similarity index 100%
rename from src/WebStarter/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.executor.liquid
rename to tests/BotSharp.Plugin.PizzaBot/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.executor.liquid
diff --git a/src/WebStarter/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.reviewer.liquid b/tests/BotSharp.Plugin.PizzaBot/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.reviewer.liquid
similarity index 100%
rename from src/WebStarter/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.reviewer.liquid
rename to tests/BotSharp.Plugin.PizzaBot/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/instruction.reviewer.liquid
diff --git a/src/WebStarter/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/task.place_pizza_order.liquid b/tests/BotSharp.Plugin.PizzaBot/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/task.place_pizza_order.liquid
similarity index 100%
rename from src/WebStarter/data/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/task.place_pizza_order.liquid
rename to tests/BotSharp.Plugin.PizzaBot/agents/dfd9b46d-d00c-40af-8a75-3fbdc2b89869/templates/task.place_pizza_order.liquid
diff --git a/src/WebStarter/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/agent.json b/tests/BotSharp.Plugin.PizzaBot/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/agent.json
similarity index 100%
rename from src/WebStarter/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/agent.json
rename to tests/BotSharp.Plugin.PizzaBot/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/agent.json
diff --git a/src/WebStarter/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/functions.json b/tests/BotSharp.Plugin.PizzaBot/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/functions.json
similarity index 100%
rename from src/WebStarter/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/functions.json
rename to tests/BotSharp.Plugin.PizzaBot/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/functions.json
diff --git a/src/WebStarter/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/instruction.liquid b/tests/BotSharp.Plugin.PizzaBot/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/instruction.liquid
similarity index 100%
rename from src/WebStarter/data/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/instruction.liquid
rename to tests/BotSharp.Plugin.PizzaBot/agents/fe8c60aa-b114-4ef3-93cb-a8efeac80f75/instruction.liquid