diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs
index 4cf63cdf..5f0489ac 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs
@@ -44,7 +44,7 @@ public abstract class ConversationHookBase : IConversationHook
public virtual Task OnConversationEnding(RoleDialogModel message)
=> Task.CompletedTask;
- public virtual Task OnCurrentTaskEnding(RoleDialogModel message)
+ public virtual Task OnTaskCompleted(RoleDialogModel message)
=> Task.CompletedTask;
public virtual Task OnHumanInterventionNeeded(RoleDialogModel message)
diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs
index 1143c492..7d943754 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs
@@ -70,7 +70,7 @@ public interface IConversationHook
///
///
///
- Task OnCurrentTaskEnding(RoleDialogModel message);
+ Task OnTaskCompleted(RoleDialogModel message);
///
/// LLM detected the whole conversation is going to be end.
diff --git a/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs b/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs
index 26d9ecef..fefade10 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs
@@ -35,7 +35,7 @@ public class FunctionCallFromLlm : RoutingArgs
public override string ToString()
{
- var route = string.IsNullOrEmpty(AgentName) ? "" : $"";
+ var route = string.IsNullOrEmpty(AgentName) ? "" : $"";
if (string.IsNullOrEmpty(Response))
{
diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/IRichMessage.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/IRichMessage.cs
index fb87f381..e04692e6 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Messaging/IRichMessage.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/IRichMessage.cs
@@ -1,9 +1,12 @@
+using BotSharp.Abstraction.Messaging.Enums;
+
namespace BotSharp.Abstraction.Messaging;
public interface IRichMessage
{
+ [JsonPropertyName("text")]
string Text { get; set; }
[JsonPropertyName("rich_type")]
- string RichType => "text";
+ string RichType => RichTypeEnum.Text;
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/GenericTemplateMessage.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/GenericTemplateMessage.cs
index 5ec4a99a..c86bca59 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/GenericTemplateMessage.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/GenericTemplateMessage.cs
@@ -11,7 +11,7 @@ public class GenericTemplateMessage : IRichMessage, ITemplateMessage
public string Text { get; set; } = string.Empty;
[JsonPropertyName("template_type")]
- public string TemplateType => TemplateTypeEnum.Generic;
+ public virtual string TemplateType { get; set; } = TemplateTypeEnum.Generic;
[JsonPropertyName("elements")]
public List Elements { get; set; } = new List();
diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
index ebeac256..82de1a81 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
@@ -10,7 +10,14 @@ public class RoutingArgs
///
[JsonPropertyName("next_action_reason")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- public string Reason { get; set; } = string.Empty;
+ public string? NextActionReason { get; set; }
+
+ [JsonPropertyName("reason")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ public string? Reason { get; set; }
+
+ [JsonPropertyName("conversation_end")]
+ public bool ConversationEnd { get; set; }
///
/// The content of replying to user
@@ -39,7 +46,7 @@ public class RoutingArgs
public override string ToString()
{
- var route = string.IsNullOrEmpty(AgentName) ? "" : $"";
+ var route = string.IsNullOrEmpty(AgentName) ? "" : $"";
if (string.IsNullOrEmpty(Response))
{
diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingRule.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingRule.cs
index b0353ce6..e0eb1da3 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingRule.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingRule.cs
@@ -23,6 +23,7 @@ public class RoutingRule
public bool Required { get; set; }
public string? RedirectTo { get; set; }
+ public string? RedirectToAgentName { get; set; }
public override string ToString()
{
diff --git a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj
index 48fd25df..da47ccb5 100644
--- a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj
+++ b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj
@@ -134,7 +134,7 @@
-
+
diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs
index e420152d..16f93e32 100644
--- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs
+++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs
@@ -153,7 +153,16 @@ public partial class ConversationService
if (response.Instruction != null)
{
var conversation = _services.GetRequiredService();
- var updatedConversation = await conversation.UpdateConversationTitle(_conversationId, response.Instruction.Reason);
+ var updatedConversation = await conversation.UpdateConversationTitle(_conversationId, response.Instruction.NextActionReason);
+
+ // Emit conversation ending hook
+ if (response.Instruction.ConversationEnd)
+ {
+ foreach (var hook in hooks)
+ {
+ await hook.OnConversationEnding(response);
+ }
+ }
}
}
}
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs b/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs
index d2f478e8..6eaaef3a 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs
@@ -57,7 +57,7 @@ public partial class RouteToAgentFn : IFunctionCallback
// Push next action agent
if (!string.IsNullOrEmpty(args.AgentName) && args.AgentName.Length < 32)
{
- _context.Push(args.AgentName, args.Reason);
+ _context.Push(args.AgentName, args.NextActionReason);
states.SetState("next_action_agent", args.AgentName, isNeedVersion: true);
}
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs
index 5a7b7c4b..bbd4fbb1 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs
@@ -1,5 +1,3 @@
-using BotSharp.Abstraction.Functions.Models;
-using BotSharp.Abstraction.Routing;
using BotSharp.Abstraction.Routing.Settings;
namespace BotSharp.Core.Routing.Handlers;
@@ -16,12 +14,15 @@ public class ConversationEndRoutingHandler : RoutingHandlerBase, IRoutingHandler
new ParameterPropertyDef("response", "response content to user")
};
+ public List Planers => new List
+ {
+ };
+
public ConversationEndRoutingHandler(IServiceProvider services, ILogger logger, RoutingSettings settings)
: base(services, logger, settings)
{
}
-
public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message)
{
var response = new RoleDialogModel(AgentRole.Assistant, inst.Response)
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs
index 1d12d4b5..5283b48d 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs
@@ -1,5 +1,3 @@
-using BotSharp.Abstraction.Functions.Models;
-using BotSharp.Abstraction.Routing;
using BotSharp.Abstraction.Routing.Settings;
namespace BotSharp.Core.Routing.Handlers;
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs
index 24a048ae..ad4d3cab 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs
@@ -1,6 +1,3 @@
-using BotSharp.Abstraction.Functions.Models;
-using BotSharp.Abstraction.Routing;
-using BotSharp.Abstraction.Routing.Models;
using BotSharp.Abstraction.Routing.Settings;
using BotSharp.Core.Routing.Planning;
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskCompletedRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskCompletedRoutingHandler.cs
new file mode 100644
index 00000000..bb553266
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskCompletedRoutingHandler.cs
@@ -0,0 +1,65 @@
+using BotSharp.Abstraction.Routing.Settings;
+using BotSharp.Core.Routing.Planning;
+
+namespace BotSharp.Core.Routing.Handlers;
+
+public class TaskCompletedRoutingHandler : RoutingHandlerBase, IRoutingHandler
+{
+ public string Name => "task_completed";
+
+ public string Description => "User task is completed.";
+
+ public List Parameters => new List
+ {
+ new ParameterPropertyDef("reason", "why the task is completed")
+ {
+ Required = true
+ },
+ new ParameterPropertyDef("response", "polite response when the task is completed")
+ {
+ Required = true
+ },
+ new ParameterPropertyDef("conversation_end", "whether to end this conversation, true or false")
+ {
+ Required = true,
+ Type = "boolean"
+ },
+ new ParameterPropertyDef("abandoned_arguments", "the arguments next task can't reuse")
+ };
+
+ public List Planers => new List
+ {
+ nameof(NaivePlanner),
+ nameof(HFPlanner)
+ };
+
+ public TaskCompletedRoutingHandler(IServiceProvider services, ILogger logger, RoutingSettings settings)
+ : base(services, logger, settings)
+ {
+ }
+
+ public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message)
+ {
+ var response = new RoleDialogModel(AgentRole.Assistant, inst.Response)
+ {
+ CurrentAgentId = message.CurrentAgentId,
+ MessageId = message.MessageId,
+ StopCompletion = true,
+ FunctionName = inst.Function,
+ Instruction = inst,
+ };
+
+ _dialogs.Add(response);
+
+ var hooks = _services.GetServices()
+ .OrderBy(x => x.Priority)
+ .ToList();
+
+ foreach (var hook in hooks)
+ {
+ await hook.OnTaskCompleted(response);
+ }
+
+ return true;
+ }
+}
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs
deleted file mode 100644
index 5e431f84..00000000
--- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using BotSharp.Abstraction.Functions.Models;
-using BotSharp.Abstraction.Routing;
-using BotSharp.Abstraction.Routing.Settings;
-using BotSharp.Core.Routing.Planning;
-
-namespace BotSharp.Core.Routing.Handlers;
-
-public class TaskEndRoutingHandler : RoutingHandlerBase, IRoutingHandler
-{
- public string Name => "task_end";
-
- public string Description => "Call this function when current task is completed.";
-
- public List Parameters => new List
- {
- new ParameterPropertyDef("abandoned_arguments", "the arguments next task can't reuse")
- };
-
- public List Planers => new List
- {
- nameof(HFPlanner)
- };
-
- public TaskEndRoutingHandler(IServiceProvider services, ILogger logger, RoutingSettings settings)
- : base(services, logger, settings)
- {
- }
-
- public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message)
- {
- var hooks = _services.GetServices()
- .OrderBy(x => x.Priority)
- .ToList();
-
- Task.WaitAll(hooks
- .Select(h => h.OnCurrentTaskEnding(message))
- .ToArray());
-
- return true;
- }
-}
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Planning/SequentialPlanner.cs b/src/Infrastructure/BotSharp.Core/Routing/Planning/SequentialPlanner.cs
index ff094770..b6f613e0 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Planning/SequentialPlanner.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Planning/SequentialPlanner.cs
@@ -31,7 +31,7 @@ public class SequentialPlanner : IPlaner
if (decomposation.TotalRemainingSteps > 0 && _lastInst != null)
{
_lastInst.Response = decomposation.Description;
- _lastInst.Reason = $"Having {decomposation.TotalRemainingSteps} steps left.";
+ _lastInst.NextActionReason = $"Having {decomposation.TotalRemainingSteps} steps left.";
return _lastInst;
}
else if (decomposation.TotalRemainingSteps == 0 || decomposation.ShouldStop)
@@ -102,7 +102,7 @@ public class SequentialPlanner : IPlaner
if (decomposation.TotalRemainingSteps > 0)
{
inst.Response = decomposation.Description;
- inst.Reason = $"{decomposation.TotalRemainingSteps} steps left.";
+ inst.NextActionReason = $"{decomposation.TotalRemainingSteps} steps left.";
inst.HandleDialogsByPlanner = true;
}
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Planning/TwoStagePlanner/FirstStagePlan.cs b/src/Infrastructure/BotSharp.Core/Routing/Planning/TwoStagePlanner/FirstStagePlan.cs
index 6b4bb672..76e697a5 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Planning/TwoStagePlanner/FirstStagePlan.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Planning/TwoStagePlanner/FirstStagePlan.cs
@@ -19,6 +19,9 @@ public class FirstStagePlan
[JsonPropertyName("related_tables")]
public string[] Tables { get; set; } = new string[0];
+ [JsonPropertyName("related_urls")]
+ public string[] Urls { get; set; } = new string[0];
+
[JsonPropertyName("input_args")]
public JsonDocument[] Parameters { get; set; } = new JsonDocument[0];
diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs
index e9abdc04..87e55840 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs
@@ -106,6 +106,11 @@ public class RoutingContext : IRoutingContext
await hook.OnAgentDequeued(agentId, currentAgentId, reason: reason)
).Wait();
+ if (string.IsNullOrEmpty(currentAgentId))
+ {
+ return;
+ }
+
// Run the routing rule
var agency = _services.GetRequiredService();
var agent = agency.LoadAgent(currentAgentId).Result;
@@ -117,7 +122,7 @@ public class RoutingContext : IRoutingContext
{
Function = "route_to_agent",
AgentName = agent.Name,
- Reason = $"User manually route to agent {agent.Name}"
+ NextActionReason = $"User manually route to agent {agent.Name}"
})
};
diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs
index 8e2560bb..622926e7 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs
@@ -54,7 +54,7 @@ public partial class RoutingService : IRoutingService
{
Function = "route_to_agent",
Question = message.Content,
- Reason = message.Content,
+ NextActionReason = message.Content,
AgentName = agent.Name,
OriginalAgent = agent.Name,
ExecutingDirectly = true
diff --git a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/instruction.liquid b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/instruction.liquid
index 990052cf..d7d0f359 100644
--- a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/instruction.liquid
+++ b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/instruction.liquid
@@ -7,10 +7,12 @@ You're {{router.name}} ({{router.description}}). Follow these steps to handle us
6. Please do not make up any parameters when there is no exact information available, leave it blank.
7. Response must be in JSON format.
+{% if routing_requirements and routing_requirements != empty %}
[REQUIREMENTS]
{% for requirement in routing_requirements %}
# {{ requirement }}
{% endfor %}
+{% endif %}
[FUNCTIONS]
{% for handler in routing_handlers %}
diff --git a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/planner_prompt.naive.liquid b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/planner_prompt.naive.liquid
index 2bf2698c..80aba1b9 100644
--- a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/planner_prompt.naive.liquid
+++ b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/planner_prompt.naive.liquid
@@ -3,5 +3,5 @@ Route to the appropriate agent last handled agent based on the context.
{% if expected_next_action_agent != empty -%}
Expected next action agent is {{ expected_next_action_agent }}.
{%- endif %}
-Try to keep the User Goal Agent be consistent as previous goal agent.
+If user completes the task, use function task_completed.
If user wants to speak to customer service, use function human_intervention_needed.
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs
index 1a9389ef..5d7f7b56 100644
--- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs
+++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs
@@ -29,7 +29,23 @@ public class AgentController : ControllerBase
{
AgentIds = new List { id }
});
- return agents.Items.FirstOrDefault();
+
+ var targetAgent = agents.Items.FirstOrDefault();
+ var redirectAgentIds = targetAgent.RoutingRules
+ .Where(x => !string.IsNullOrEmpty(x.RedirectTo))
+ .Select(x => x.RedirectTo).ToList();
+ var redirectAgents = await _agentService.GetAgents(new AgentFilter
+ {
+ AgentIds = redirectAgentIds
+ });
+ foreach (var rule in targetAgent.RoutingRules)
+ {
+ var found = redirectAgents.Items.FirstOrDefault(x => x.Id == rule.RedirectTo);
+ if (found == null) continue;
+
+ rule.RedirectToAgentName = found.Name;
+ }
+ return targetAgent;
}
[HttpGet("/agents")]
diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs
index bc90877a..757b31a3 100644
--- a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs
+++ b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs
@@ -41,6 +41,7 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook, IR
_routingCtx = routingCtx;
}
+ #region IConversationHook
public override async Task OnMessageReceived(RoleDialogModel message)
{
var conversationId = _state.GetConversationId();
@@ -156,6 +157,38 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook, IR
}
}
+ public override async Task OnTaskCompleted(RoleDialogModel message)
+ {
+ var conversationId = _state.GetConversationId();
+ var log = $"{message.Content}";
+ var agent = await _agentService.LoadAgent(message.CurrentAgentId);
+
+ var input = new ContentLogInputModel(conversationId, message)
+ {
+ Name = agent.Name,
+ Source = ContentLogSource.FunctionCall,
+ Log = log
+ };
+ await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", BuildContentLog(input));
+ }
+
+ public override async Task OnConversationEnding(RoleDialogModel message)
+ {
+ var conversationId = _state.GetConversationId();
+ var log = $"Conversation ended";
+ var agent = await _agentService.LoadAgent(message.CurrentAgentId);
+
+ var input = new ContentLogInputModel(conversationId, message)
+ {
+ Name = agent?.Name ?? "System",
+ Source = ContentLogSource.FunctionCall,
+ Log = log
+ };
+ await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", BuildContentLog(input));
+ }
+
+ #endregion
+
#region IRoutingHook
public async Task OnAgentEnqueued(string agentId, string preAgentId, string? reason = null)
{
diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs
index 84e32538..fdbc29cb 100644
--- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs
+++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs
@@ -26,8 +26,11 @@ public class PlaywrightInstance : IDisposable
{
if (_contexts.ContainsKey(id))
return;
-
+#if DEBUG
string tempFolderPath = $"{Path.GetTempPath()}\\playwright";
+#else
+ string tempFolderPath = $"{Path.GetTempPath()}\\playwright\\{id}";
+#endif
_contexts[id] = await _playwright.Chromium.LaunchPersistentContextAsync(tempFolderPath, new BrowserTypeLaunchPersistentContextOptions
{
#if DEBUG
diff --git a/tests/BotSharp.Plugin.PizzaBot/Hooks/PizzaTypeConversationHook.cs b/tests/BotSharp.Plugin.PizzaBot/Hooks/PizzaTypeConversationHook.cs
index 558fa047..6fb34772 100644
--- a/tests/BotSharp.Plugin.PizzaBot/Hooks/PizzaTypeConversationHook.cs
+++ b/tests/BotSharp.Plugin.PizzaBot/Hooks/PizzaTypeConversationHook.cs
@@ -13,4 +13,9 @@ public class PizzaTypeConversationHook : ConversationHookBase
}
return;
}
+
+ public override Task OnTaskCompleted(RoleDialogModel message)
+ {
+ return base.OnTaskCompleted(message);
+ }
}