diff --git a/BotSharp.sln b/BotSharp.sln
index e4653913f..69974a1df 100644
--- a/BotSharp.sln
+++ b/BotSharp.sln
@@ -151,6 +151,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.GiteeAI", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.ImageHandler", "src\Plugins\BotSharp.Plugin.ImageHandler\BotSharp.Plugin.ImageHandler.csproj", "{242F2D93-FCCE-4982-8075-F3052ECCA92C}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.FuzzySharp", "src\Plugins\BotSharp.Plugin.FuzzySharp\BotSharp.Plugin.FuzzySharp.csproj", "{E7C243B9-E751-B3B4-8F16-95C76CA90D31}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -639,6 +641,14 @@ Global
{242F2D93-FCCE-4982-8075-F3052ECCA92C}.Release|Any CPU.Build.0 = Release|Any CPU
{242F2D93-FCCE-4982-8075-F3052ECCA92C}.Release|x64.ActiveCfg = Release|Any CPU
{242F2D93-FCCE-4982-8075-F3052ECCA92C}.Release|x64.Build.0 = Release|Any CPU
+ {E7C243B9-E751-B3B4-8F16-95C76CA90D31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E7C243B9-E751-B3B4-8F16-95C76CA90D31}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E7C243B9-E751-B3B4-8F16-95C76CA90D31}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E7C243B9-E751-B3B4-8F16-95C76CA90D31}.Debug|x64.Build.0 = Debug|Any CPU
+ {E7C243B9-E751-B3B4-8F16-95C76CA90D31}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E7C243B9-E751-B3B4-8F16-95C76CA90D31}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E7C243B9-E751-B3B4-8F16-95C76CA90D31}.Release|x64.ActiveCfg = Release|Any CPU
+ {E7C243B9-E751-B3B4-8F16-95C76CA90D31}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -712,6 +722,7 @@ Global
{FC63C875-E880-D8BB-B8B5-978AB7B62983} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
{50B57066-3267-1D10-0F72-D2F5CC494F2C} = {D5293208-2BEF-42FC-A64C-5954F61720BA}
{242F2D93-FCCE-4982-8075-F3052ECCA92C} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
+ {E7C243B9-E751-B3B4-8F16-95C76CA90D31} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A9969D89-C98B-40A5-A12B-FC87E55B3A19}
diff --git a/Directory.Build.props b/Directory.Build.props
index 0879abfcc..d93cb20fb 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -2,7 +2,7 @@
net8.0
12.0
- 5.1.0
+ 5.2.0
true
false
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 60ef84da7..53e2bb5be 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -5,31 +5,33 @@
true
+
+
-
-
-
+
+
-
+
-
+
-
+
+
-
+
-
+
-
-
-
+
+
+
@@ -38,82 +40,82 @@
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
-
+
+
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
+
-
-
+
+
-
+
-
-
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/README.md b/README.md
index 89fcc0e82..81e8bafd6 100644
--- a/README.md
+++ b/README.md
@@ -115,8 +115,11 @@ BotSharp uses component design, the kernel is kept to a minimum, and business fu
- BotSharp.Plugin.Dashboard
- BotSharp.Plugin.RoutingSpeeder
- BotSharp.Plugin.AudioHandler
+- BotSharp.Plugin.ChartHandler
- BotSharp.Plugin.EmailHandler
+- BotSharp.Plugin.ExcelHandler
- BotSharp.Plugin.FileHandler
+- BotSharp.Plugin.ImageHandler
- BotSharp.Plugin.HttpHandler
- BotSharp.Plugin.SqlDriver
- BotSharp.Plugin.WebDriver
@@ -130,7 +133,7 @@ BotSharp uses component design, the kernel is kept to a minimum, and business fu
- [x] MCP
- [x] Realtime
- [ ] Computer Use
-- [x] Browser Use
+- [ ] Browser Use
- [x] Database Assistant
- [x] Code Interpreter
- [x] Conversation Management
diff --git a/src/BotSharp.AppHost/BotSharp.AppHost.csproj b/src/BotSharp.AppHost/BotSharp.AppHost.csproj
index 26ff84a82..962ffa903 100644
--- a/src/BotSharp.AppHost/BotSharp.AppHost.csproj
+++ b/src/BotSharp.AppHost/BotSharp.AppHost.csproj
@@ -1,5 +1,6 @@
-
+
+
Exe
net8.0
diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/AgentHookBase.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/AgentHookBase.cs
index 770acd016..ff3ac9408 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Agents/AgentHookBase.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Agents/AgentHookBase.cs
@@ -29,7 +29,7 @@ public virtual bool OnAgentLoading(ref string id)
return true;
}
- public virtual bool OnInstructionLoaded(string template, Dictionary dict)
+ public virtual bool OnInstructionLoaded(string template, IDictionary dict)
{
dict["current_date"] = $"{DateTime.Now:MMM dd, yyyy}";
dict["current_time"] = $"{DateTime.Now:hh:mm tt}";
diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentHook.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentHook.cs
index 19e29642c..ca6f042a7 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentHook.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentHook.cs
@@ -16,7 +16,7 @@ public interface IAgentHook : IHookBase
///
bool OnAgentLoading(ref string id);
- bool OnInstructionLoaded(string template, Dictionary dict);
+ bool OnInstructionLoaded(string template, IDictionary dict);
bool OnFunctionsLoaded(List functions);
diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs
index e7b054d79..d0284b224 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs
@@ -1,4 +1,6 @@
using BotSharp.Abstraction.Agents.Options;
+using BotSharp.Abstraction.Coding.Models;
+using BotSharp.Abstraction.Coding.Options;
using BotSharp.Abstraction.Functions.Models;
using BotSharp.Abstraction.Plugins.Models;
using BotSharp.Abstraction.Repositories.Filters;
@@ -30,18 +32,18 @@ public interface IAgentService
///
Task InheritAgent(Agent agent);
- string RenderInstruction(Agent agent, Dictionary? renderData = null);
+ string RenderInstruction(Agent agent, IDictionary? renderData = null);
- string RenderTemplate(Agent agent, string templateName, Dictionary? renderData = null);
+ string RenderTemplate(Agent agent, string templateName, IDictionary? renderData = null);
- bool RenderFunction(Agent agent, FunctionDef def, Dictionary? renderData = null);
+ bool RenderFunction(Agent agent, FunctionDef def, IDictionary? renderData = null);
- FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def, Dictionary? renderData = null);
+ FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def, IDictionary? renderData = null);
- (string, IEnumerable) PrepareInstructionAndFunctions(Agent agent, Dictionary? renderData = null, StringComparer? comparer = null);
+ (string, IEnumerable) PrepareInstructionAndFunctions(Agent agent, IDictionary? renderData = null, StringComparer? comparer = null);
- bool RenderVisibility(string? visibilityExpression, Dictionary dict);
- Dictionary CollectRenderData(Agent agent);
+ bool RenderVisibility(string? visibilityExpression, IDictionary dict);
+ IDictionary CollectRenderData(Agent agent);
///
@@ -51,7 +53,7 @@ public interface IAgentService
/// Original agent information
Task GetAgent(string id);
- Task DeleteAgent(string id);
+ Task DeleteAgent(string id, AgentDeleteOptions? options = null);
Task UpdateAgent(Agent agent, AgentField updateField);
///
@@ -70,9 +72,15 @@ public interface IAgentService
Task> GetAgentCodeScripts(string agentId, AgentCodeScriptFilter? filter = null)
=> Task.FromResult(new List());
- Task GetAgentCodeScript(string agentId, string scriptName, string scriptType = AgentCodeScriptType.Src)
- => Task.FromResult(string.Empty);
+ Task GetAgentCodeScript(string agentId, string scriptName, string scriptType = AgentCodeScriptType.Src)
+ => Task.FromResult((AgentCodeScript?)null);
Task UpdateAgentCodeScripts(string agentId, List codeScripts, AgentCodeScriptUpdateOptions? options = null)
=> Task.FromResult(false);
+
+ Task DeleteAgentCodeScripts(string agentId, List? codeScripts = null)
+ => Task.FromResult(false);
+
+ Task GenerateCodeScript(string agentId, string text, CodeGenHandleOptions? options = null)
+ => Task.FromResult(new CodeGenerationResult());
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentCodeScript.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentCodeScript.cs
index 840d67210..aa673e32b 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentCodeScript.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentCodeScript.cs
@@ -5,13 +5,16 @@ public class AgentCodeScript : AgentCodeScriptBase
public string Id { get; set; }
public string AgentId { get; set; } = null!;
+ public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
+ public DateTime UpdatedTime { get; set; } = DateTime.UtcNow;
+
public AgentCodeScript() : base()
{
}
public override string ToString()
{
- return $"{CodePath}";
+ return base.ToString();
}
}
@@ -26,4 +29,9 @@ public class AgentCodeScriptBase
public string ScriptType { get; set; } = null!;
public string CodePath => $"{ScriptType}/{Name}";
+
+ public override string ToString()
+ {
+ return $"{CodePath}";
+ }
}
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentLlmConfig.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentLlmConfig.cs
index 6ed259a3f..dcd716bb9 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentLlmConfig.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentLlmConfig.cs
@@ -43,18 +43,11 @@ public class AgentLlmConfig
public string? ReasoningEffortLevel { get; set; }
///
- /// Image generation config
+ /// Image composition config
///
- [JsonPropertyName("image_generation")]
+ [JsonPropertyName("image_composition")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- public LlmImageGenerationConfig? ImageGeneration { get; set; }
-
- ///
- /// Image edit config
- ///
- [JsonPropertyName("image_edit")]
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- public LlmImageEditConfig? ImageEdit { get; set; }
+ public LlmImageCompositionConfig? ImageComposition { get; set; }
///
/// Audio transcription config
@@ -71,12 +64,7 @@ public class AgentLlmConfig
public LlmRealtimeConfig? Realtime { get; set; }
}
-
-public class LlmImageGenerationConfig : LlmProviderModel
-{
-}
-
-public class LlmImageEditConfig : LlmProviderModel
+public class LlmImageCompositionConfig : LlmProviderModel
{
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentRule.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentRule.cs
index 87a08a894..75c0985a8 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentRule.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentRule.cs
@@ -3,11 +3,11 @@ namespace BotSharp.Abstraction.Agents.Models;
public class AgentRule
{
[JsonPropertyName("trigger_name")]
- public string TriggerName { get; set; }
+ public string TriggerName { get; set; } = string.Empty;
[JsonPropertyName("disabled")]
public bool Disabled { get; set; }
[JsonPropertyName("criteria")]
- public string Criteria { get; set; }
+ public string Criteria { get; set; } = string.Empty;
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Options/AgentCodeScriptUpdateOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Options/AgentCodeScriptUpdateOptions.cs
index 476e42fc9..153694e9d 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Agents/Options/AgentCodeScriptUpdateOptions.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Options/AgentCodeScriptUpdateOptions.cs
@@ -4,5 +4,6 @@ namespace BotSharp.Abstraction.Agents.Options;
public class AgentCodeScriptUpdateOptions : AgentCodeScriptDbUpdateOptions
{
+ [JsonPropertyName("delete_if_not_included")]
public bool DeleteIfNotIncluded { get; set; }
-}
+}
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Options/AgentDeleteOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Options/AgentDeleteOptions.cs
new file mode 100644
index 000000000..5df6737c7
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Options/AgentDeleteOptions.cs
@@ -0,0 +1,14 @@
+namespace BotSharp.Abstraction.Agents.Options;
+
+public class AgentDeleteOptions
+{
+ [JsonPropertyName("delete_role_agents")]
+ public bool DeleteRoleAgents { get; set; }
+
+ [JsonPropertyName("delete_user_agents")]
+ public bool DeleteUserAgents { get; set; }
+
+ [JsonPropertyName("to_delete_code_scripts")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ public List? ToDeleteCodeScripts { get; set; }
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Settings/AgentSettings.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Settings/AgentSettings.cs
index 887c437ec..f6d4835ec 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Agents/Settings/AgentSettings.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Settings/AgentSettings.cs
@@ -10,6 +10,5 @@ public class AgentSettings
///
/// This is the default LLM config for agent
///
- public AgentLlmConfig LlmConfig { get; set; }
- = new AgentLlmConfig();
+ public AgentLlmConfig LlmConfig { get; set; } = new();
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Chart/IBotSharpChartService.cs b/src/Infrastructure/BotSharp.Abstraction/Chart/IBotSharpChartService.cs
deleted file mode 100644
index 0e1cab8c4..000000000
--- a/src/Infrastructure/BotSharp.Abstraction/Chart/IBotSharpChartService.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using BotSharp.Abstraction.Chart.Models;
-using BotSharp.Abstraction.Chart.Options;
-
-namespace BotSharp.Abstraction.Chart;
-
-public interface IBotSharpChartService
-{
- public string Provider { get; }
-
- Task GetConversationChartData(string conversationId, string messageId, ChartDataOptions options)
- => throw new NotImplementedException();
-
- Task GetConversationChartCode(string conversationId, string messageId, ChartCodeOptions options)
- => throw new NotImplementedException();
-}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Chart/IChartProcessor.cs b/src/Infrastructure/BotSharp.Abstraction/Chart/IChartProcessor.cs
new file mode 100644
index 000000000..7f8cfd4d8
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Chart/IChartProcessor.cs
@@ -0,0 +1,12 @@
+using BotSharp.Abstraction.Chart.Models;
+using BotSharp.Abstraction.Chart.Options;
+
+namespace BotSharp.Abstraction.Chart;
+
+public interface IChartProcessor
+{
+ public string Provider { get; }
+
+ Task GetConversationChartDataAsync(string conversationId, string messageId, ChartDataOptions? options = null)
+ => throw new NotImplementedException();
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Chart/Models/ChartCodeResult.cs b/src/Infrastructure/BotSharp.Abstraction/Chart/Models/ChartCodeResult.cs
deleted file mode 100644
index 143ba218d..000000000
--- a/src/Infrastructure/BotSharp.Abstraction/Chart/Models/ChartCodeResult.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace BotSharp.Abstraction.Chart.Models;
-
-public class ChartCodeResult
-{
- public string Code { get; set; }
- public string Language { get; set; }
-}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Coding/Contexts/CodeExecutionContext.cs b/src/Infrastructure/BotSharp.Abstraction/Coding/Contexts/CodeExecutionContext.cs
new file mode 100644
index 000000000..e2ec38a5a
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Coding/Contexts/CodeExecutionContext.cs
@@ -0,0 +1,7 @@
+namespace BotSharp.Abstraction.Coding.Contexts;
+
+public class CodeExecutionContext
+{
+ public AgentCodeScript CodeScript { get; set; }
+ public List Arguments { get; set; } = [];
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Coding/Enums/BuiltInCodeProcessor.cs b/src/Infrastructure/BotSharp.Abstraction/Coding/Enums/BuiltInCodeProcessor.cs
new file mode 100644
index 000000000..cdbf76a99
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Coding/Enums/BuiltInCodeProcessor.cs
@@ -0,0 +1,6 @@
+namespace BotSharp.Abstraction.Coding.Enums;
+
+public static class BuiltInCodeProcessor
+{
+ public const string PyInterpreter = "botsharp-py-interpreter";
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Coding/ICodeProcessor.cs b/src/Infrastructure/BotSharp.Abstraction/Coding/ICodeProcessor.cs
index 1fe083f01..bd34eb257 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Coding/ICodeProcessor.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Coding/ICodeProcessor.cs
@@ -1,5 +1,7 @@
+using BotSharp.Abstraction.Coding.Models;
using BotSharp.Abstraction.Coding.Options;
using BotSharp.Abstraction.Coding.Responses;
+using System.Threading;
namespace BotSharp.Abstraction.Coding;
@@ -7,6 +9,24 @@ public interface ICodeProcessor
{
string Provider { get; }
- Task RunAsync(string codeScript, CodeInterpretOptions? options = null)
+ ///
+ /// Run code script
+ ///
+ /// The code script to run
+ /// Code script execution options
+ /// The cancellation token
+ ///
+ ///
+ CodeInterpretResponse Run(string codeScript, CodeInterpretOptions? options = null, CancellationToken cancellationToken = default)
+ => throw new NotImplementedException();
+
+ ///
+ /// Generate code script
+ ///
+ /// User requirement to generate code script
+ /// Code script generation options
+ ///
+ ///
+ Task GenerateCodeScriptAsync(string text, CodeGenerationOptions? options = null)
=> throw new NotImplementedException();
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Coding/Models/CodeExecutionResponseModel.cs b/src/Infrastructure/BotSharp.Abstraction/Coding/Models/CodeExecutionResponseModel.cs
new file mode 100644
index 000000000..7045f1ac9
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Coding/Models/CodeExecutionResponseModel.cs
@@ -0,0 +1,12 @@
+using BotSharp.Abstraction.Coding.Responses;
+
+namespace BotSharp.Abstraction.Coding.Models;
+
+public class CodeExecutionResponseModel
+{
+ public string CodeProcessor { get; set; } = default!;
+ public AgentCodeScript CodeScript { get; set; }
+ public IDictionary? Arguments { get; set; }
+ public string Text { get; set; } = default!;
+ public CodeInterpretResponse? ExecutionResult { get; set; }
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Coding/Models/CodeGenerationResult.cs b/src/Infrastructure/BotSharp.Abstraction/Coding/Models/CodeGenerationResult.cs
new file mode 100644
index 000000000..83544f985
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Coding/Models/CodeGenerationResult.cs
@@ -0,0 +1,7 @@
+namespace BotSharp.Abstraction.Coding.Models;
+
+public class CodeGenerationResult : ResponseBase
+{
+ public string Content { get; set; }
+ public string Language { get; set; }
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Coding/Options/CodeGenHandleOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Coding/Options/CodeGenHandleOptions.cs
new file mode 100644
index 000000000..963cb8a15
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Coding/Options/CodeGenHandleOptions.cs
@@ -0,0 +1,28 @@
+namespace BotSharp.Abstraction.Coding.Options;
+
+public class CodeGenHandleOptions : CodeGenerationOptions
+{
+ ///
+ /// Code processor provider
+ ///
+ [JsonPropertyName("processor")]
+ public string? Processor { get; set; }
+
+ ///
+ /// Whether to save the generated code script to db
+ ///
+ [JsonPropertyName("save_to_db")]
+ public bool SaveToDb { get; set; }
+
+ ///
+ /// Code script name (e.g., demo.py)
+ ///
+ [JsonPropertyName("script_name")]
+ public string? ScriptName { get; set; }
+
+ ///
+ /// Code script type (i.e., src, test)
+ ///
+ [JsonPropertyName("script_type")]
+ public string? ScriptType { get; set; } = AgentCodeScriptType.Src;
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Coding/Options/CodeGenerationOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Coding/Options/CodeGenerationOptions.cs
new file mode 100644
index 000000000..de886f5ef
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Coding/Options/CodeGenerationOptions.cs
@@ -0,0 +1,31 @@
+namespace BotSharp.Abstraction.Coding.Options;
+
+public class CodeGenerationOptions : LlmConfigBase
+{
+ ///
+ /// Agent id to get instruction
+ ///
+ [JsonPropertyName("agent_id")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ public string? AgentId { get; set; }
+
+ ///
+ /// Template (prompt) name
+ ///
+ [JsonPropertyName("template_name")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ public string? TemplateName { get; set; }
+
+ ///
+ /// Programming language
+ ///
+ [JsonPropertyName("programming_language")]
+ public string? ProgrammingLanguage { get; set; }
+
+ ///
+ /// Data that can be used to fill in the prompt
+ ///
+ [JsonPropertyName("data")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ public Dictionary? Data { get; set; }
+}
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Abstraction/Coding/Options/CodeInterpretOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Coding/Options/CodeInterpretOptions.cs
index b563b03de..7152c46ef 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Coding/Options/CodeInterpretOptions.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Coding/Options/CodeInterpretOptions.cs
@@ -1,11 +1,9 @@
-using System.Threading;
-
namespace BotSharp.Abstraction.Coding.Options;
public class CodeInterpretOptions
{
public string? ScriptName { get; set; }
public IEnumerable? Arguments { get; set; }
- public bool UseMutex { get; set; }
- public CancellationToken? CancellationToken { get; set; }
+ public bool UseLock { get; set; }
+ public bool UseProcess { get; set; }
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Coding/Responses/CodeInterpretResponse.cs b/src/Infrastructure/BotSharp.Abstraction/Coding/Responses/CodeInterpretResponse.cs
index a07c7a1fe..8d41f9853 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Coding/Responses/CodeInterpretResponse.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Coding/Responses/CodeInterpretResponse.cs
@@ -1,8 +1,11 @@
namespace BotSharp.Abstraction.Coding.Responses;
-public class CodeInterpretResponse
+public class CodeInterpretResponse : ResponseBase
{
public string Result { get; set; } = string.Empty;
- public bool Success { get; set; }
- public string? ErrorMsg { get; set; }
+
+ public override string ToString()
+ {
+ return Result.IfNullOrEmptyAs(ErrorMsg.IfNullOrEmptyAs($"Success: {Success}"))!;
+ }
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Coding/Settings/CodingSettings.cs b/src/Infrastructure/BotSharp.Abstraction/Coding/Settings/CodingSettings.cs
new file mode 100644
index 000000000..49747798e
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Coding/Settings/CodingSettings.cs
@@ -0,0 +1,22 @@
+namespace BotSharp.Abstraction.Coding.Settings;
+
+public class CodingSettings
+{
+ public CodeScriptGenerationSettings? CodeGeneration { get; set; }
+
+ public CodeScriptExecutionSettings? CodeExecution { get; set; }
+}
+
+public class CodeScriptGenerationSettings : LlmConfigBase
+{
+ public string? Processor { get; set; }
+ public int? MessageLimit { get; set; }
+}
+
+public class CodeScriptExecutionSettings
+{
+ public string? Processor { get; set; }
+ public bool UseLock { get; set; }
+ public bool UseProcess { get; set; }
+ public int TimeoutSeconds { get; set; } = 3;
+}
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Abstraction/Files/Options/FileHandleOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Files/Options/FileHandleOptions.cs
index 31a2ab46c..60b3ffc34 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Files/Options/FileHandleOptions.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Files/Options/FileHandleOptions.cs
@@ -1,27 +1,7 @@
namespace BotSharp.Abstraction.Files.Options;
-public class FileHandleOptions
+public class FileHandleOptions : LlmConfigBase
{
- ///
- /// Llm provider
- ///
- public string? Provider { get; set; }
-
- ///
- /// llm model
- ///
- public string? Model { get; set; }
-
- ///
- /// Llm maximum output tokens
- ///
- public int? MaxOutputTokens { get; set; }
-
- ///
- /// Reasoning effort level
- ///
- public string? ReasoningEfforLevel { get; set; }
-
///
/// Instruction
///
diff --git a/src/Infrastructure/BotSharp.Abstraction/Files/Options/SelectFileOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Files/Options/SelectFileOptions.cs
index 2f8d348ea..2c769cb8d 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Files/Options/SelectFileOptions.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Files/Options/SelectFileOptions.cs
@@ -13,7 +13,7 @@ public class SelectFileOptions : LlmConfigBase
public string? TemplateName { get; set; }
///
- /// Description that user provides to select files
+ /// User description to select files
///
public string? Description { get; set; }
diff --git a/src/Infrastructure/BotSharp.Abstraction/Files/Proccessors/IFileProcessor.cs b/src/Infrastructure/BotSharp.Abstraction/Files/Proccessors/IFileProcessor.cs
index 19ab437c9..fbcced77a 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Files/Proccessors/IFileProcessor.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Files/Proccessors/IFileProcessor.cs
@@ -1,5 +1,7 @@
using BotSharp.Abstraction.Files.Options;
using BotSharp.Abstraction.Files.Responses;
+using BotSharp.Abstraction.Knowledges.Options;
+using BotSharp.Abstraction.Knowledges.Responses;
namespace BotSharp.Abstraction.Files.Proccessors;
@@ -9,4 +11,7 @@ public interface IFileProcessor
Task HandleFilesAsync(Agent agent, string text, IEnumerable files, FileHandleOptions? options = null)
=> throw new NotImplementedException();
+
+ Task GetFileKnowledgeAsync(FileBinaryDataModel file, FileKnowledgeHandleOptions? options = null)
+ => throw new NotImplementedException();
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Files/Responses/FileHandleResponse.cs b/src/Infrastructure/BotSharp.Abstraction/Files/Responses/FileHandleResponse.cs
index 6957ed0fc..67de6eb7d 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Files/Responses/FileHandleResponse.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Files/Responses/FileHandleResponse.cs
@@ -1,8 +1,6 @@
namespace BotSharp.Abstraction.Files.Responses;
-public class FileHandleResponse
+public class FileHandleResponse : ResponseBase
{
public string Result { get; set; } = string.Empty;
- public bool Success { get; set; }
- public string? ErrorMsg { get; set; }
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Instructs/Contexts/CodeInstructContext.cs b/src/Infrastructure/BotSharp.Abstraction/Instructs/Contexts/CodeInstructContext.cs
deleted file mode 100644
index d6dae85f6..000000000
--- a/src/Infrastructure/BotSharp.Abstraction/Instructs/Contexts/CodeInstructContext.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace BotSharp.Abstraction.Instructs.Contexts;
-
-public class CodeInstructContext
-{
- public string CodeScript { get; set; }
- public List Arguments { get; set; } = [];
-}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Instructs/IInstructHook.cs b/src/Infrastructure/BotSharp.Abstraction/Instructs/IInstructHook.cs
index c275691b4..54fc80a90 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Instructs/IInstructHook.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Instructs/IInstructHook.cs
@@ -1,5 +1,6 @@
+using BotSharp.Abstraction.Coding.Contexts;
+using BotSharp.Abstraction.Coding.Models;
using BotSharp.Abstraction.Hooks;
-using BotSharp.Abstraction.Instructs.Contexts;
using BotSharp.Abstraction.Instructs.Models;
namespace BotSharp.Abstraction.Instructs;
@@ -10,6 +11,6 @@ public interface IInstructHook : IHookBase
Task AfterCompletion(Agent agent, InstructResult result) => Task.CompletedTask;
Task OnResponseGenerated(InstructResponseModel response) => Task.CompletedTask;
- Task BeforeCodeExecution(Agent agent, RoleDialogModel message, CodeInstructContext context) => Task.CompletedTask;
- Task AfterCodeExecution(Agent agent, InstructResult result) => Task.CompletedTask;
+ Task BeforeCodeExecution(Agent agent, CodeExecutionContext context) => Task.CompletedTask;
+ Task AfterCodeExecution(Agent agent, CodeExecutionResponseModel response) => Task.CompletedTask;
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Instructs/InstructHookBase.cs b/src/Infrastructure/BotSharp.Abstraction/Instructs/InstructHookBase.cs
index 9209684cf..f5758434c 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Instructs/InstructHookBase.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Instructs/InstructHookBase.cs
@@ -1,3 +1,5 @@
+using BotSharp.Abstraction.Coding.Contexts;
+using BotSharp.Abstraction.Coding.Models;
using BotSharp.Abstraction.Instructs.Models;
namespace BotSharp.Abstraction.Instructs;
@@ -20,4 +22,14 @@ public virtual async Task OnResponseGenerated(InstructResponseModel response)
{
await Task.CompletedTask;
}
+
+ public virtual async Task BeforeCodeExecution(Agent agent, CodeExecutionContext context)
+ {
+ await Task.CompletedTask;
+ }
+
+ public virtual async Task AfterCodeExecution(Agent agent, CodeExecutionResponseModel response)
+ {
+ await Task.CompletedTask;
+ }
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Instructs/Options/CodeInstructOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Instructs/Options/CodeInstructOptions.cs
index 89684cfdf..182196753 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Instructs/Options/CodeInstructOptions.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Instructs/Options/CodeInstructOptions.cs
@@ -2,7 +2,31 @@ namespace BotSharp.Abstraction.Instructs.Options;
public class CodeInstructOptions
{
+ ///
+ /// Code processor provider
+ ///
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("processor")]
public string? Processor { get; set; }
- public string? CodeScriptName { get; set; }
+
+ ///
+ /// Code script name
+ ///
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("script_name")]
+ public string? ScriptName { get; set; }
+
+ ///
+ /// Code script name
+ ///
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("script_type")]
+ public string? ScriptType { get; set; }
+
+ ///
+ /// Arguments
+ ///
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("arguments")]
public List? Arguments { get; set; }
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Instructs/Options/FileInstructOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Instructs/Options/FileInstructOptions.cs
index bb575f49d..b673589db 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Instructs/Options/FileInstructOptions.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Instructs/Options/FileInstructOptions.cs
@@ -2,5 +2,10 @@ namespace BotSharp.Abstraction.Instructs.Options;
public class FileInstructOptions
{
+ ///
+ /// File processor provider
+ ///
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("processor")]
public string? Processor { get; set; }
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Instructs/Options/InstructOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Instructs/Options/InstructOptions.cs
index cc5a76cd5..b2ff66fba 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Instructs/Options/InstructOptions.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Instructs/Options/InstructOptions.cs
@@ -35,5 +35,5 @@ public class InstructOptions
///
/// Image convert provider
///
- public string? ImageConvertProvider { get; set; }
+ public string? ImageConverter { get; set; }
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/IKnowledgeService.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/IKnowledgeService.cs
index 767615fe5..393898b5f 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Knowledges/IKnowledgeService.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/IKnowledgeService.cs
@@ -36,8 +36,9 @@ public interface IKnowledgeService
///
///
///
+ ///
///
- Task UploadDocumentsToKnowledge(string collectionName, IEnumerable files, ChunkOption? option = null);
+ Task UploadDocumentsToKnowledge(string collectionName, IEnumerable files, KnowledgeDocOptions? options = null);
///
/// Save document content to knowledgebase without saving the document
///
diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/IPhraseCollection.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/IPhraseCollection.cs
new file mode 100644
index 000000000..9238e3220
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/IPhraseCollection.cs
@@ -0,0 +1,7 @@
+namespace BotSharp.Abstraction.Knowledges;
+
+public interface IPhraseCollection
+{
+ Task>> LoadVocabularyAsync();
+ Task> LoadSynonymMappingAsync();
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/IPhraseService.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/IPhraseService.cs
new file mode 100644
index 000000000..1ca84024a
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/IPhraseService.cs
@@ -0,0 +1,6 @@
+namespace BotSharp.Abstraction.Knowledges;
+
+public interface IPhraseService
+{
+ Task> SearchPhrasesAsync(string term);
+}
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/FileKnowledgeModel.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/FileKnowledgeModel.cs
new file mode 100644
index 000000000..0b79001e5
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/FileKnowledgeModel.cs
@@ -0,0 +1,18 @@
+using BotSharp.Abstraction.VectorStorage.Models;
+
+namespace BotSharp.Abstraction.Knowledges.Models;
+
+public class FileKnowledgeModel
+{
+ public IEnumerable Contents { get; set; } = [];
+ public IDictionary? Payload { get; set; }
+}
+
+
+public class FileKnowledgeWrapper
+{
+ public Guid FileId { get; set; }
+ public string? FileSource { get; set; }
+ public FileBinaryDataModel FileData { get; set; }
+ public IEnumerable FileKnowledges { get; set; } = [];
+}
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Abstraction/Files/Models/KnowledgeFileModel.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/KnowledgeFileModel.cs
similarity index 87%
rename from src/Infrastructure/BotSharp.Abstraction/Files/Models/KnowledgeFileModel.cs
rename to src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/KnowledgeFileModel.cs
index c3ca76fc7..49f9f1615 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Files/Models/KnowledgeFileModel.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/KnowledgeFileModel.cs
@@ -1,4 +1,4 @@
-namespace BotSharp.Abstraction.Files.Models;
+namespace BotSharp.Abstraction.Knowledges.Models;
public class KnowledgeFileModel
{
diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/SearchPhrasesResult.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/SearchPhrasesResult.cs
new file mode 100644
index 000000000..64dc0c18f
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/SearchPhrasesResult.cs
@@ -0,0 +1,11 @@
+
+namespace BotSharp.Abstraction.Knowledges.Models;
+
+public class SearchPhrasesResult
+{
+ public string Token { get; set; } = string.Empty;
+ public List Sources { get; set; } = new();
+ public string CanonicalForm { get; set; } = string.Empty;
+ public string MatchType { get; set; } = string.Empty;
+ public double Confidence { get; set; }
+}
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/Options/FileKnowledgeHandleOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Options/FileKnowledgeHandleOptions.cs
new file mode 100644
index 000000000..9b891ab28
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Options/FileKnowledgeHandleOptions.cs
@@ -0,0 +1,34 @@
+namespace BotSharp.Abstraction.Knowledges.Options;
+
+public class FileKnowledgeHandleOptions : LlmConfigBase
+{
+ ///
+ /// Agent id
+ ///
+ public string? AgentId { get; set; }
+
+ ///
+ /// Instruction
+ ///
+ public string? Instruction { get; set; }
+
+ ///
+ /// Message from user
+ ///
+ public string? UserMessage { get; set; }
+
+ ///
+ /// Template name in Agent
+ ///
+ public string? TemplateName { get; set; }
+
+ ///
+ /// The upstream where the file llm is invoked
+ ///
+ public string? InvokeFrom { get; set; }
+
+ ///
+ /// Data that is used to render instruction
+ ///
+ public Dictionary? Data { get; set; }
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/Options/KnowledgeDocOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Options/KnowledgeDocOptions.cs
new file mode 100644
index 000000000..52c123426
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Options/KnowledgeDocOptions.cs
@@ -0,0 +1,6 @@
+namespace BotSharp.Abstraction.Knowledges.Options;
+
+public class KnowledgeDocOptions : FileKnowledgeHandleOptions
+{
+ public string? Processor { get; set; }
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/Responses/FileKnowledgeResponse.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Responses/FileKnowledgeResponse.cs
new file mode 100644
index 000000000..27b5d6967
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Responses/FileKnowledgeResponse.cs
@@ -0,0 +1,6 @@
+namespace BotSharp.Abstraction.Knowledges.Responses;
+
+public class FileKnowledgeResponse : ResponseBase
+{
+ public IEnumerable Knowledges { get; set; } = [];
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/MLTasks/Filters/LlmConfigFilter.cs b/src/Infrastructure/BotSharp.Abstraction/MLTasks/Filters/LlmConfigFilter.cs
new file mode 100644
index 000000000..89ec04103
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/MLTasks/Filters/LlmConfigFilter.cs
@@ -0,0 +1,13 @@
+using BotSharp.Abstraction.MLTasks.Settings;
+
+namespace BotSharp.Abstraction.MLTasks.Filters;
+
+public class LlmConfigFilter
+{
+ public List? Providers { get; set; }
+ public List? ModelIds { get; set; }
+ public List? ModelNames { get; set; }
+ public List? ModelTypes { get; set; }
+ public List? ModelCapabilities { get; set; }
+ public bool? MultiModal { get; set; }
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/MLTasks/ILlmProviderService.cs b/src/Infrastructure/BotSharp.Abstraction/MLTasks/ILlmProviderService.cs
index f70a9496e..da8a8f534 100644
--- a/src/Infrastructure/BotSharp.Abstraction/MLTasks/ILlmProviderService.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/MLTasks/ILlmProviderService.cs
@@ -1,12 +1,13 @@
+using BotSharp.Abstraction.MLTasks.Filters;
using BotSharp.Abstraction.MLTasks.Settings;
namespace BotSharp.Abstraction.MLTasks;
public interface ILlmProviderService
{
- LlmModelSetting GetSetting(string provider, string model);
+ LlmModelSetting? GetSetting(string provider, string model);
List GetProviders();
- LlmModelSetting GetProviderModel(string provider, string id, bool? multiModal = null, LlmModelType? modelType = null, bool imageGenerate = false);
+ LlmModelSetting? GetProviderModel(string provider, string id, bool? multiModal = null, LlmModelType? modelType = null, IEnumerable? capabilities = null);
List GetProviderModels(string provider);
- List GetLlmConfigs(LlmConfigOptions? options = null);
+ List GetLlmConfigs(LlmConfigFilter? filter = null);
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/MLTasks/Settings/LlmConfigOptions.cs b/src/Infrastructure/BotSharp.Abstraction/MLTasks/Settings/LlmConfigOptions.cs
deleted file mode 100644
index eae417a41..000000000
--- a/src/Infrastructure/BotSharp.Abstraction/MLTasks/Settings/LlmConfigOptions.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace BotSharp.Abstraction.MLTasks.Settings;
-
-public class LlmConfigOptions
-{
- public LlmModelType? Type { get; set; }
- public bool? MultiModal { get; set; }
- public bool? ImageGeneration { get; set; }
-}
diff --git a/src/Infrastructure/BotSharp.Abstraction/MLTasks/Settings/LlmModelSetting.cs b/src/Infrastructure/BotSharp.Abstraction/MLTasks/Settings/LlmModelSetting.cs
index 1bc7ef743..77bd46b28 100644
--- a/src/Infrastructure/BotSharp.Abstraction/MLTasks/Settings/LlmModelSetting.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/MLTasks/Settings/LlmModelSetting.cs
@@ -31,17 +31,13 @@ public class LlmModelSetting
public string ApiKey { get; set; } = null!;
public string? Endpoint { get; set; }
public LlmModelType Type { get; set; } = LlmModelType.Chat;
+ public List Capabilities { get; set; } = [];
///
- /// If true, allow sending images/vidoes to this model
+ /// If true, allow sending images/videos to this model
///
public bool MultiModal { get; set; }
- ///
- /// If true, allow generating images
- ///
- public bool ImageGeneration { get; set; }
-
///
/// Settings for embedding
///
@@ -122,6 +118,7 @@ public class ImageGenerationSetting
public class ImageEditSetting
{
public ModelSettingBase? Size { get; set; }
+ public ModelSettingBase? Quality { get; set; }
public ModelSettingBase? ResponseFormat { get; set; }
public ModelSettingBase? Background { get; set; }
}
@@ -172,10 +169,30 @@ public class LlmCostSetting
public enum LlmModelType
{
+ All = 0,
Text = 1,
Chat = 2,
Image = 3,
Embedding = 4,
Audio = 5,
Realtime = 6,
+ Web = 7
}
+
+public enum LlmModelCapability
+{
+ All = 0,
+ Text = 1,
+ Chat = 2,
+ ImageReading = 3,
+ ImageGeneration = 4,
+ ImageEdit = 5,
+ ImageVariation = 6,
+ ImageComposition = 7,
+ Embedding = 8,
+ AudioTranscription = 9,
+ AudioGeneration = 10,
+ Realtime = 11,
+ WebSearch = 12,
+ PdfReading = 13
+}
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Abstraction/Models/ResponseBase.cs b/src/Infrastructure/BotSharp.Abstraction/Models/ResponseBase.cs
new file mode 100644
index 000000000..cb381aebe
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Models/ResponseBase.cs
@@ -0,0 +1,11 @@
+namespace BotSharp.Abstraction.Models;
+
+public class ResponseBase
+{
+ [JsonPropertyName("success")]
+ public bool Success { get; set; }
+
+ [JsonPropertyName("error_message")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ public string? ErrorMsg { get; set; }
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Options/BotSharpOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Options/BotSharpOptions.cs
index b8609422d..63469bcd8 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Options/BotSharpOptions.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Options/BotSharpOptions.cs
@@ -9,9 +9,11 @@ public class BotSharpOptions
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
AllowTrailingCommas = true,
- WriteIndented = true
+ WriteIndented = true,
+ ReferenceHandler = ReferenceHandler.IgnoreCycles
};
+
private JsonSerializerOptions _jsonSerializerOptions;
public JsonSerializerOptions JsonSerializerOptions
diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentCodeScriptFilter.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentCodeScriptFilter.cs
index 530bb4aa5..14848d717 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentCodeScriptFilter.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentCodeScriptFilter.cs
@@ -7,6 +7,6 @@ public class AgentCodeScriptFilter
public static AgentCodeScriptFilter Empty()
{
- return new AgentCodeScriptFilter();
+ return new();
}
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/InstructLogFilter.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/InstructLogFilter.cs
index aeec7b18a..4ff78e4dd 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/InstructLogFilter.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/InstructLogFilter.cs
@@ -8,6 +8,7 @@ public class InstructLogFilter : Pagination
public List? TemplateNames { get; set; }
public List? UserIds { get; set; }
public List? States { get; set; }
+ public string? SimilarTemplateName { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs
index 31b1da97a..374271b9f 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs
@@ -1,3 +1,4 @@
+using BotSharp.Abstraction.Agents.Options;
using BotSharp.Abstraction.Knowledges.Filters;
using BotSharp.Abstraction.Loggers.Models;
using BotSharp.Abstraction.Plugins.Models;
@@ -81,7 +82,7 @@ void BulkInsertUserAgents(List userAgents)
=> throw new NotImplementedException();
bool DeleteAgents()
=> throw new NotImplementedException();
- bool DeleteAgent(string agentId)
+ bool DeleteAgent(string agentId, AgentDeleteOptions? options = null)
=> throw new NotImplementedException();
List GetAgentResponses(string agentId, string prefix, string intent)
=> throw new NotImplementedException();
@@ -113,7 +114,7 @@ bool DeleteAgentTasks(string agentId, List? taskIds = null)
#region Agent Code
List GetAgentCodeScripts(string agentId, AgentCodeScriptFilter? filter = null)
=> throw new NotImplementedException();
- string? GetAgentCodeScript(string agentId, string scriptName, string scriptType = AgentCodeScriptType.Src)
+ AgentCodeScript? GetAgentCodeScript(string agentId, string scriptName, string scriptType = AgentCodeScriptType.Src)
=> throw new NotImplementedException();
bool UpdateAgentCodeScripts(string agentId, List scripts, AgentCodeScriptDbUpdateOptions? options = null)
=> throw new NotImplementedException();
diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/Options/AgentCodeScriptDbUpdateOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/Options/AgentCodeScriptDbUpdateOptions.cs
index 5f6045129..2dde049bf 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Repositories/Options/AgentCodeScriptDbUpdateOptions.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/Options/AgentCodeScriptDbUpdateOptions.cs
@@ -2,5 +2,6 @@ namespace BotSharp.Abstraction.Repositories.Options;
public class AgentCodeScriptDbUpdateOptions
{
+ [JsonPropertyName("is_upsert")]
public bool IsUpsert { get; set; }
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Rules/IRuleEngine.cs b/src/Infrastructure/BotSharp.Abstraction/Rules/IRuleEngine.cs
index c870f145f..c7a6d847b 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Rules/IRuleEngine.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Rules/IRuleEngine.cs
@@ -2,5 +2,15 @@ namespace BotSharp.Abstraction.Rules;
public interface IRuleEngine
{
- Task> Triggered(IRuleTrigger trigger, string data, List? states = null);
+ ///
+ /// Trigger the rule that is subscribed by agents.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task> Triggered(IRuleTrigger trigger, string text, IEnumerable? states = null, RuleTriggerOptions? options = null)
+ => throw new NotImplementedException();
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Rules/IRuleTrigger.cs b/src/Infrastructure/BotSharp.Abstraction/Rules/IRuleTrigger.cs
index 7b6c9bc25..c7ad59d9a 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Rules/IRuleTrigger.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Rules/IRuleTrigger.cs
@@ -1,3 +1,5 @@
+using System.Text.Json;
+
namespace BotSharp.Abstraction.Rules;
public interface IRuleTrigger
@@ -9,4 +11,14 @@ public interface IRuleTrigger
string EntityType { get; set; }
string EntityId { get; set; }
+
+ ///
+ /// The default arguments as input to code trigger (display purpose)
+ ///
+ JsonDocument OutputArgs => JsonDocument.Parse("{}");
+
+ ///
+ /// Explain the purpose of rule trigger (display purpose)
+ ///
+ string Statement => string.Empty;
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Rules/Options/RuleTriggerOptions.cs b/src/Infrastructure/BotSharp.Abstraction/Rules/Options/RuleTriggerOptions.cs
new file mode 100644
index 000000000..068052b0b
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Rules/Options/RuleTriggerOptions.cs
@@ -0,0 +1,26 @@
+using System.Text.Json;
+
+namespace BotSharp.Abstraction.Rules.Options;
+
+public class RuleTriggerOptions
+{
+ ///
+ /// Code processor provider
+ ///
+ public string? CodeProcessor { get; set; }
+
+ ///
+ /// Code script name
+ ///
+ public string? CodeScriptName { get; set; }
+
+ ///
+ /// Argument name as an input key to the code script
+ ///
+ public string? ArgumentName { get; set; }
+
+ ///
+ /// Json arguments as an input value to the code script
+ ///
+ public JsonDocument? ArgumentContent { get; set; }
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Templating/ITemplateRender.cs b/src/Infrastructure/BotSharp.Abstraction/Templating/ITemplateRender.cs
index fecc36c45..9a555f9c7 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Templating/ITemplateRender.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Templating/ITemplateRender.cs
@@ -2,6 +2,6 @@ namespace BotSharp.Abstraction.Templating;
public interface ITemplateRender
{
- string Render(string template, Dictionary dict);
+ string Render(string template, IDictionary dict);
void RegisterType(Type type);
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs b/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs
index a8403dfa1..18e92b28c 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs
@@ -15,6 +15,15 @@ public interface IAuthenticationHook
Task Authenticate(string id, string password)
=> Task.FromResult(new User());
+ ///
+ /// Renew token for authentication
+ ///
+ ///
+ ///
+ ///
+ Task RenewAuthentication(string refreshToken, string? accessToken = null)
+ => Task.FromResult((User?)null);
+
///
/// Add extra claims to user
///
diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs b/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs
index d03687ffa..a7b3da1f7 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs
@@ -19,8 +19,8 @@ public interface IUserService
Task GetAffiliateToken(string authorization);
Task GetAdminToken(string authorization);
Task GetToken(string authorization);
+ Task RenewToken(string refreshToken, string? accessToken = null);
Task CreateTokenByUser(User user);
- Task RenewToken();
Task GetMyProfile();
Task VerifyUserNameExisting(string userName);
Task VerifyEmailExisting(string email);
diff --git a/src/Infrastructure/BotSharp.Abstraction/Using.cs b/src/Infrastructure/BotSharp.Abstraction/Using.cs
index d20775375..ca0cbe7f7 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Using.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Using.cs
@@ -21,4 +21,6 @@
global using BotSharp.Abstraction.Knowledges.Models;
global using BotSharp.Abstraction.Crontab.Models;
global using BotSharp.Abstraction.MCP.Models;
-global using BotSharp.Abstraction.Settings;
\ No newline at end of file
+global using BotSharp.Abstraction.Settings;
+global using BotSharp.Abstraction.Rules.Options;
+global using BotSharp.Abstraction.Coding.Settings;
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Abstraction/Utilities/ObjectExtensions.cs b/src/Infrastructure/BotSharp.Abstraction/Utilities/ObjectExtensions.cs
new file mode 100644
index 000000000..a36516c8a
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Utilities/ObjectExtensions.cs
@@ -0,0 +1,68 @@
+using BotSharp.Abstraction.Options;
+using System.Text.Json;
+using JsonSerializer = System.Text.Json.JsonSerializer;
+
+namespace BotSharp.Abstraction.Utilities;
+
+public static class ObjectExtensions
+{
+ private static readonly JsonSerializerOptions _defaultJsonOptions = new()
+ {
+ PropertyNameCaseInsensitive = true,
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
+ AllowTrailingCommas = true,
+ ReferenceHandler = ReferenceHandler.IgnoreCycles
+ };
+
+ public static T? DeepClone(this T? inputObj, Action? modifier = null, BotSharpOptions? options = null) where T : class
+ {
+ if (inputObj == null)
+ {
+ return null;
+ }
+
+ try
+ {
+ var json = JsonSerializer.Serialize(inputObj, options?.JsonSerializerOptions ?? _defaultJsonOptions);
+ var outputObj = JsonSerializer.Deserialize(json, options?.JsonSerializerOptions ?? _defaultJsonOptions);
+ if (modifier != null && outputObj != null)
+ {
+ modifier(outputObj);
+ }
+
+ return outputObj;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"DeepClone Error in {nameof(DeepClone)} for {typeof(T).Name}: {ex}");
+ return null;
+ }
+ }
+
+ public static TOutput? DeepClone(this TInput? inputObj, Action? modifier = null, BotSharpOptions? options = null)
+ where TInput : class
+ where TOutput : class
+ {
+ if (inputObj == null)
+ {
+ return null;
+ }
+
+ try
+ {
+ var json = JsonSerializer.Serialize(inputObj, options?.JsonSerializerOptions ?? _defaultJsonOptions);
+ var outputObj = JsonSerializer.Deserialize(json, options?.JsonSerializerOptions ?? _defaultJsonOptions);
+ if (modifier != null && outputObj != null)
+ {
+ modifier(outputObj);
+ }
+
+ return outputObj;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"DeepClone Error in {nameof(DeepClone)} for {typeof(TInput).Name} and {typeof(TOutput).Name}: {ex}");
+ return null;
+ }
+ }
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Utilities/StringExtensions.cs b/src/Infrastructure/BotSharp.Abstraction/Utilities/StringExtensions.cs
index 8e2fd9bbf..e26f663d1 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Utilities/StringExtensions.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Utilities/StringExtensions.cs
@@ -11,12 +11,18 @@ public static class StringExtensions
public static string SubstringMax(this string str, int maxLength)
{
if (string.IsNullOrEmpty(str))
+ {
return str;
+ }
if (str.Length > maxLength)
+ {
return str.Substring(0, maxLength);
+ }
else
+ {
return str;
+ }
}
public static string[] SplitByNewLine(this string input)
@@ -39,14 +45,20 @@ public static string RemoveNewLine(this string input)
public static bool IsEqualTo(this string? str1, string? str2, StringComparison option = StringComparison.OrdinalIgnoreCase)
{
- if (str1 == null) return str2 == null;
+ if (str1 == null)
+ {
+ return str2 == null;
+ }
return str1.Equals(str2, option);
}
public static string CleanStr(this string? str)
{
- if (string.IsNullOrWhiteSpace(str)) return string.Empty;
+ if (string.IsNullOrWhiteSpace(str))
+ {
+ return string.Empty;
+ }
return str.Replace(" ", "").Replace("\t", "").Replace("\n", "").Replace("\r", "");
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorSearchParamModel.cs b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorSearchParamModel.cs
new file mode 100644
index 000000000..8e14b05ca
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorSearchParamModel.cs
@@ -0,0 +1,7 @@
+namespace BotSharp.Abstraction.VectorStorage.Models;
+
+public class VectorSearchParamModel
+{
+ [JsonPropertyName("exact_search")]
+ public bool? ExactSearch { get; set; }
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Options/VectorSearchOptions.cs b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Options/VectorSearchOptions.cs
index 1e0141a86..4ba0c81c8 100644
--- a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Options/VectorSearchOptions.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Options/VectorSearchOptions.cs
@@ -10,6 +10,7 @@ public class VectorSearchOptions
public int? Limit { get; set; } = 5;
public float? Confidence { get; set; } = 0.5f;
public bool WithVector { get; set; }
+ public VectorSearchParamModel? SearchParam { get; set; }
public static VectorSearchOptions Default()
{
diff --git a/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabWatcher.cs b/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabWatcher.cs
index 288458430..ccd89cf45 100644
--- a/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabWatcher.cs
+++ b/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabWatcher.cs
@@ -36,7 +36,8 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
await RunCronChecker(scope.ServiceProvider);
await Task.Delay(1000, stoppingToken);
});
- if (isLocked == false)
+
+ if (!isLocked)
{
await Task.Delay(1000, stoppingToken);
}
diff --git a/src/Infrastructure/BotSharp.Core.Rules/Engines/RuleEngine.cs b/src/Infrastructure/BotSharp.Core.Rules/Engines/RuleEngine.cs
index 1b3006663..2d52ef6d2 100644
--- a/src/Infrastructure/BotSharp.Core.Rules/Engines/RuleEngine.cs
+++ b/src/Infrastructure/BotSharp.Core.Rules/Engines/RuleEngine.cs
@@ -1,25 +1,41 @@
+using BotSharp.Abstraction.Agents.Models;
+using BotSharp.Abstraction.Coding;
+using BotSharp.Abstraction.Coding.Contexts;
+using BotSharp.Abstraction.Coding.Enums;
+using BotSharp.Abstraction.Coding.Models;
+using BotSharp.Abstraction.Coding.Settings;
using BotSharp.Abstraction.Conversations;
+using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Models;
using BotSharp.Abstraction.Repositories.Filters;
+using BotSharp.Abstraction.Rules.Options;
using BotSharp.Abstraction.Utilities;
using Microsoft.Extensions.Logging;
using System.Data;
+using System.Text.Json;
namespace BotSharp.Core.Rules.Engines;
public class RuleEngine : IRuleEngine
{
private readonly IServiceProvider _services;
- private readonly ILogger _logger;
+ private readonly ILogger _logger;
+ private readonly CodingSettings _codingSettings;
- public RuleEngine(IServiceProvider services, ILogger logger)
+ public RuleEngine(
+ IServiceProvider services,
+ ILogger logger,
+ CodingSettings codingSettings)
{
_services = services;
_logger = logger;
+ _codingSettings = codingSettings;
}
- public async Task> Triggered(IRuleTrigger trigger, string data, List? states = null)
+ public async Task> Triggered(IRuleTrigger trigger, string text, IEnumerable? states = null, RuleTriggerOptions? options = null)
{
+ var newConversationIds = new List();
+
// Pull all user defined rules
var agentService = _services.GetRequiredService();
var agents = await agentService.GetAgents(new AgentFilter
@@ -30,25 +46,29 @@ public async Task> Triggered(IRuleTrigger trigger, string da
}
});
- var preFilteredAgents = agents.Items.Where(x =>
- x.Rules.Exists(r => r.TriggerName == trigger.Name &&
- !x.Disabled)).ToList();
-
- // Trigger the agents
- var instructService = _services.GetRequiredService();
- var newConversationIds = new List();
-
- foreach (var agent in preFilteredAgents)
+ // Trigger agents
+ var filteredAgents = agents.Items.Where(x => x.Rules.Exists(r => r.TriggerName.IsEqualTo(trigger.Name) && !x.Disabled)).ToList();
+ foreach (var agent in filteredAgents)
{
+ // Code trigger
+ if (options != null)
+ {
+ var isTriggered = await TriggerCodeScript(agent, trigger.Name, options);
+ if (!isTriggered)
+ {
+ continue;
+ }
+ }
+
var convService = _services.GetRequiredService();
var conv = await convService.NewConversation(new Conversation
{
Channel = trigger.Channel,
- Title = data,
+ Title = text,
AgentId = agent.Id
});
- var message = new RoleDialogModel(AgentRole.User, data);
+ var message = new RoleDialogModel(AgentRole.User, text);
var allStates = new List
{
@@ -69,27 +89,127 @@ await convService.SendMessage(agent.Id,
convService.SaveStates();
newConversationIds.Add(conv.Id);
+ }
+
+ return newConversationIds;
+ }
- /*foreach (var rule in agent.Rules)
+ #region Private methods
+ private async Task TriggerCodeScript(Agent agent, string triggerName, RuleTriggerOptions options)
+ {
+ if (string.IsNullOrWhiteSpace(agent?.Id))
+ {
+ return false;
+ }
+
+ var provider = options.CodeProcessor ?? BuiltInCodeProcessor.PyInterpreter;
+ var processor = _services.GetServices().FirstOrDefault(x => x.Provider.IsEqualTo(provider));
+ if (processor == null)
+ {
+ _logger.LogWarning($"Unable to find code processor: {provider}.");
+ return false;
+ }
+
+ var agentService = _services.GetRequiredService();
+ var scriptName = options.CodeScriptName ?? $"{triggerName}_rule.py";
+ var codeScript = await agentService.GetAgentCodeScript(agent.Id, scriptName, scriptType: AgentCodeScriptType.Src);
+
+ var msg = $"rule trigger ({triggerName}) code script ({scriptName}) in agent ({agent.Name}) => args: {options.ArgumentContent?.RootElement.GetRawText()}.";
+
+ if (codeScript == null || string.IsNullOrWhiteSpace(codeScript.Content))
+ {
+ _logger.LogWarning($"Unable to find {msg}.");
+ return false;
+ }
+
+ try
+ {
+ var hooks = _services.GetHooks(agent.Id);
+
+ var arguments = BuildArguments(options.ArgumentName, options.ArgumentContent);
+ var context = new CodeExecutionContext
{
- var userSay = $"===Input data with Before and After values===\r\n{data}\r\n\r\n===Trigger Criteria===\r\n{rule.Criteria}\r\n\r\nJust output 1 or 0 without explanation: ";
+ CodeScript = codeScript,
+ Arguments = arguments
+ };
- var result = await instructService.Execute(BuiltInAgentId.RulesInterpreter, new RoleDialogModel(AgentRole.User, userSay), "criteria_check", "#TEMPLATE#");
+ foreach (var hook in hooks)
+ {
+ await hook.BeforeCodeExecution(agent, context);
+ }
- // Check if meet the criteria
- if (result.Text == "1")
- {
- // Hit rule
- _logger.LogInformation($"Hit rule {rule.TriggerName} {rule.EntityType} {rule.EventName}, {data}");
+ var (useLock, useProcess, timeoutSeconds) = GetCodeExecutionConfig();
+ using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSeconds));
+ var response = processor.Run(codeScript.Content, options: new()
+ {
+ ScriptName = scriptName,
+ Arguments = arguments,
+ UseLock = useLock,
+ UseProcess = useProcess
+ }, cancellationToken: cts.Token);
- await convService.SendMessage(agent.Id,
- new RoleDialogModel(AgentRole.User, $"The conversation was triggered by {rule.Criteria}"),
- null,
- msg => Task.CompletedTask);
- }
- }*/
+ var codeResponse = new CodeExecutionResponseModel
+ {
+ CodeProcessor = processor.Provider,
+ CodeScript = codeScript,
+ Arguments = arguments.DistinctBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value ?? string.Empty),
+ ExecutionResult = response
+ };
+
+ foreach (var hook in hooks)
+ {
+ await hook.AfterCodeExecution(agent, codeResponse);
+ }
+
+ if (response == null || !response.Success)
+ {
+ _logger.LogWarning($"Failed to handle {msg}");
+ return false;
+ }
+
+ bool result;
+ LogLevel logLevel;
+ if (response.Result.IsEqualTo("true"))
+ {
+ logLevel = LogLevel.Information;
+ result = true;
+ }
+ else
+ {
+ logLevel = LogLevel.Warning;
+ result = false;
+ }
+
+ _logger.Log(logLevel, $"Code script execution result ({response}) from {msg}");
+ return result;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, $"Error when handling {msg}");
+ return false;
}
+ }
- return newConversationIds;
+ private List BuildArguments(string? name, JsonDocument? args)
+ {
+ var keyValues = new List();
+ if (args != null)
+ {
+ keyValues.Add(new KeyValue(name ?? "trigger_args", args.RootElement.GetRawText()));
+ }
+ return keyValues;
+ }
+
+ private (bool, bool, int) GetCodeExecutionConfig()
+ {
+ var codeExecution = _codingSettings.CodeExecution;
+ var defaultTimeoutSeconds = 3;
+
+ var useLock = codeExecution?.UseLock ?? false;
+ var useProcess = codeExecution?.UseProcess ?? false;
+ var timeoutSeconds = codeExecution?.TimeoutSeconds > 0 ? codeExecution.TimeoutSeconds : defaultTimeoutSeconds;
+
+ return (useLock, useProcess, timeoutSeconds);
}
+ #endregion
}
diff --git a/src/Infrastructure/BotSharp.Core/Agents/AgentPlugin.cs b/src/Infrastructure/BotSharp.Core/Agents/AgentPlugin.cs
index 41e13da4c..575385455 100644
--- a/src/Infrastructure/BotSharp.Core/Agents/AgentPlugin.cs
+++ b/src/Infrastructure/BotSharp.Core/Agents/AgentPlugin.cs
@@ -57,9 +57,10 @@ public bool AttachMenu(List menu)
{
SubMenu = new List
{
+ new PluginMenuDef("Agents", link: "page/agent"), // icon: "bx bx-bot",
new PluginMenuDef("Routing", link: "page/agent/router"), // icon: "bx bx-map-pin"
- new PluginMenuDef("Evaluating", link: "page/agent/evaluator") { Roles = new List { UserRole.Root, UserRole.Admin } }, // icon: "bx bx-task"
- new PluginMenuDef("Agents", link: "page/agent"), // icon: "bx bx-bot"
+ new PluginMenuDef("Evaluating", link: "page/agent/evaluator") { Roles = [UserRole.Root, UserRole.Admin] }, // icon: "bx bx-task"
+ new PluginMenuDef("Coding", link: "page/agent/code-scripts") { Roles = [UserRole.Root, UserRole.Admin] },
}
});
diff --git a/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs b/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs
index a8bafdd25..cadeb3b47 100644
--- a/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs
+++ b/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs
@@ -70,12 +70,18 @@ public override void OnAgentUtilityLoaded(Agent agent)
foreach (var utility in innerUtilities)
{
var isVisible = agentService.RenderVisibility(utility.VisibilityExpression, renderDict);
- if (!isVisible || utility.Items.IsNullOrEmpty()) continue;
+ if (!isVisible || utility.Items.IsNullOrEmpty())
+ {
+ continue;
+ }
foreach (var item in utility.Items)
{
isVisible = agentService.RenderVisibility(item.VisibilityExpression, renderDict);
- if (!isVisible) continue;
+ if (!isVisible)
+ {
+ continue;
+ }
if (item.FunctionName?.StartsWith(UTIL_PREFIX) == true)
{
diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CodeScripts.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CodeScripts.cs
deleted file mode 100644
index 5c7c8bc00..000000000
--- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CodeScripts.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using BotSharp.Abstraction.Agents.Options;
-
-namespace BotSharp.Core.Agents.Services;
-
-public partial class AgentService
-{
- public async Task> GetAgentCodeScripts(string agentId, AgentCodeScriptFilter? filter = null)
- {
- var db = _services.GetRequiredService();
- var scripts = db.GetAgentCodeScripts(agentId, filter);
- return await Task.FromResult(scripts);
- }
-
- public async Task GetAgentCodeScript(string agentId, string scriptName, string scriptType = AgentCodeScriptType.Src)
- {
- var db = _services.GetRequiredService();
- var script = db.GetAgentCodeScript(agentId, scriptName, scriptType);
- return await Task.FromResult(script);
- }
-
- public async Task UpdateAgentCodeScripts(string agentId, List codeScripts, AgentCodeScriptUpdateOptions? options = null)
- {
- if (string.IsNullOrWhiteSpace(agentId) || codeScripts.IsNullOrEmpty())
- {
- return false;
- }
-
- var db = _services.GetRequiredService();
-
- var toDeleteScripts = new List();
- if (options?.DeleteIfNotIncluded == true)
- {
- var curDbScripts = await GetAgentCodeScripts(agentId);
- var codePaths = codeScripts.Select(x => x.CodePath).ToList();
- toDeleteScripts = curDbScripts.Where(x => !codePaths.Contains(x.CodePath)).ToList();
- }
-
- var updateResult = db.UpdateAgentCodeScripts(agentId, codeScripts, options);
- if (!toDeleteScripts.IsNullOrEmpty())
- {
- db.DeleteAgentCodeScripts(agentId, toDeleteScripts);
- }
-
- return updateResult;
- }
-}
diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Coding.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Coding.cs
new file mode 100644
index 000000000..ea9d336f0
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Coding.cs
@@ -0,0 +1,113 @@
+using BotSharp.Abstraction.Agents.Options;
+using BotSharp.Abstraction.Coding;
+using BotSharp.Abstraction.Coding.Enums;
+using BotSharp.Abstraction.Coding.Options;
+
+namespace BotSharp.Core.Agents.Services;
+
+public partial class AgentService
+{
+ public async Task> GetAgentCodeScripts(string agentId, AgentCodeScriptFilter? filter = null)
+ {
+ var db = _services.GetRequiredService();
+ var scripts = db.GetAgentCodeScripts(agentId, filter);
+ return await Task.FromResult(scripts);
+ }
+
+ public async Task GetAgentCodeScript(string agentId, string scriptName, string scriptType = AgentCodeScriptType.Src)
+ {
+ var db = _services.GetRequiredService();
+ var script = db.GetAgentCodeScript(agentId, scriptName, scriptType);
+ return await Task.FromResult(script);
+ }
+
+ public async Task UpdateAgentCodeScripts(string agentId, List codeScripts, AgentCodeScriptUpdateOptions? options = null)
+ {
+ if (string.IsNullOrWhiteSpace(agentId))
+ {
+ return false;
+ }
+
+ codeScripts ??= new();
+ var db = _services.GetRequiredService();
+
+ if (options?.DeleteIfNotIncluded == true && codeScripts.IsNullOrEmpty())
+ {
+ // Delete all code scripts in this agent
+ db.DeleteAgentCodeScripts(agentId);
+ return true;
+ }
+
+ var toDeleteScripts = new List();
+ if (options?.DeleteIfNotIncluded == true)
+ {
+ var curDbScripts = await GetAgentCodeScripts(agentId);
+ var codePaths = codeScripts.Select(x => x.CodePath).ToList();
+ toDeleteScripts = curDbScripts.Where(x => !codePaths.Contains(x.CodePath)).ToList();
+ }
+
+ var updateResult = db.UpdateAgentCodeScripts(agentId, codeScripts, options);
+ if (!toDeleteScripts.IsNullOrEmpty())
+ {
+ db.DeleteAgentCodeScripts(agentId, toDeleteScripts);
+ }
+
+ return updateResult;
+ }
+
+ public async Task DeleteAgentCodeScripts(string agentId, List? codeScripts = null)
+ {
+ if (string.IsNullOrWhiteSpace(agentId))
+ {
+ return false;
+ }
+
+ var db = _services.GetRequiredService();
+ var deleted = db.DeleteAgentCodeScripts(agentId, codeScripts);
+ return await Task.FromResult(deleted);
+ }
+
+ public async Task GenerateCodeScript(string agentId, string text, CodeGenHandleOptions? options = null)
+ {
+ if (string.IsNullOrWhiteSpace(agentId))
+ {
+ return new CodeGenerationResult
+ {
+ ErrorMsg = "Agent id cannot be empty."
+ };
+ }
+
+ var settings = _services.GetRequiredService();
+ var processor = options?.Processor ?? settings?.CodeGeneration?.Processor;
+ processor = !string.IsNullOrEmpty(processor) ? processor : BuiltInCodeProcessor.PyInterpreter;
+ var codeProcessor = _services.GetServices().FirstOrDefault(x => x.Provider.IsEqualTo(processor));
+ if (codeProcessor == null)
+ {
+ var errorMsg = $"Unable to find code processor {processor}.";
+ _logger.LogWarning(errorMsg);
+ return new CodeGenerationResult
+ {
+ ErrorMsg = errorMsg
+ };
+ }
+
+ var result = await codeProcessor.GenerateCodeScriptAsync(text, options);
+ if (result.Success && options?.SaveToDb == true)
+ {
+ var db = _services.GetRequiredService();
+ var scripts = new List
+ {
+ new AgentCodeScript
+ {
+ Name = options?.ScriptName ?? $"{Guid.NewGuid()}.py",
+ Content = result.Content,
+ ScriptType = options?.ScriptType ?? AgentCodeScriptType.Src
+ }
+ };
+ var saved = db.UpdateAgentCodeScripts(agentId, scripts, new() { IsUpsert = true });
+ result.Success = saved;
+ }
+
+ return result;
+ }
+}
diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs
index d61f0f3dd..5404c0d44 100644
--- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs
+++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs
@@ -127,7 +127,7 @@ private List GetFunctionsFromFile(string fileDir)
if (extension != "json") continue;
var json = File.ReadAllText(file);
- var function = JsonSerializer.Deserialize(json, _options);
+ var function = JsonSerializer.Deserialize(json, _options.JsonSerializerOptions);
functions.Add(function);
}
catch
diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.DeleteAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.DeleteAgent.cs
index 6783bf916..5237dbdc9 100644
--- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.DeleteAgent.cs
+++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.DeleteAgent.cs
@@ -1,3 +1,4 @@
+using BotSharp.Abstraction.Agents.Options;
using BotSharp.Abstraction.Users.Enums;
using BotSharp.Abstraction.Users.Models;
@@ -5,7 +6,7 @@ namespace BotSharp.Core.Agents.Services;
public partial class AgentService
{
- public async Task DeleteAgent(string id)
+ public async Task DeleteAgent(string id, AgentDeleteOptions? options = null)
{
var userService = _services.GetRequiredService();
var auth = await userService.GetUserAuthorizations(new List { id });
@@ -15,7 +16,7 @@ public async Task DeleteAgent(string id)
return false;
}
- var deleted = _db.DeleteAgent(id);
+ var deleted = _db.DeleteAgent(id, options);
return await Task.FromResult(deleted);
}
}
diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs
index 5fae2184e..e3defd95d 100644
--- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs
+++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs
@@ -41,7 +41,7 @@ public async Task> GetAgentOptions(List? agentIdsOrNames, b
return agents?.Select(x => new IdName(x.Id, x.Name))?.OrderBy(x => x.Name)?.ToList() ?? [];
}
- [SharpCache(10)]
+ [SharpCache(10, perInstanceCache: true)]
public async Task GetAgent(string id)
{
if (string.IsNullOrWhiteSpace(id) || id == Guid.Empty.ToString())
@@ -83,17 +83,34 @@ public async Task GetAgent(string id)
private void AddDefaultInstruction(Agent agent, string instruction)
{
//check if instruction is empty
- if (string.IsNullOrWhiteSpace(instruction)) return;
+ if (string.IsNullOrWhiteSpace(instruction))
+ {
+ return;
+ }
+
//check if instruction is already set
- if (agent.ChannelInstructions.Exists(p => p.Channel == string.Empty)) return;
+ var instructions = new List(agent.ChannelInstructions);
+ if (instructions.Exists(p => string.IsNullOrEmpty(p.Channel)))
+ {
+ return;
+ }
+
//Add default instruction to ChannelInstructions
- var defaultInstruction = new ChannelInstruction() { Channel = string.Empty, Instruction = instruction };
- agent.ChannelInstructions.Insert(0, defaultInstruction);
+ var defaultInstruction = new ChannelInstruction()
+ {
+ Channel = string.Empty,
+ Instruction = instruction
+ };
+ instructions.Insert(0, defaultInstruction);
+ agent.ChannelInstructions = instructions;
}
public async Task InheritAgent(Agent agent)
{
- if (string.IsNullOrWhiteSpace(agent?.InheritAgentId)) return;
+ if (string.IsNullOrWhiteSpace(agent?.InheritAgentId))
+ {
+ return;
+ }
var inheritedAgent = await GetAgent(agent.InheritAgentId);
agent.Templates.AddRange(inheritedAgent.Templates
diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs
index ef81adafd..031ee9bcf 100644
--- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs
+++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs
@@ -10,12 +10,18 @@ public partial class AgentService
// [SharpCache(10, perInstanceCache: true)]
public async Task LoadAgent(string id, bool loadUtility = true)
{
- if (string.IsNullOrEmpty(id) || id == Guid.Empty.ToString()) return null;
+ if (string.IsNullOrEmpty(id) || id == Guid.Empty.ToString())
+ {
+ return null;
+ }
HookEmitter.Emit(_services, hook => hook.OnAgentLoading(ref id), id);
var agent = await GetAgent(id);
- if (agent == null) return null;
+ if (agent == null)
+ {
+ return null;
+ }
agent.TemplateDict = [];
agent.SecondaryInstructions = [];
@@ -25,8 +31,8 @@ public async Task LoadAgent(string id, bool loadUtility = true)
OverrideInstructionByChannel(agent);
AddOrUpdateParameters(agent);
- // Populate state into dictionary
- PopulateState(agent.TemplateDict);
+ // Populate state
+ PopulateState(agent);
// After agent is loaded
HookEmitter.Emit(_services, hook => {
@@ -68,30 +74,32 @@ public async Task LoadAgent(string id, bool loadUtility = true)
private void OverrideInstructionByChannel(Agent agent)
{
- var instructions = agent.ChannelInstructions;
- if (instructions.IsNullOrEmpty()) return;
+ var instructions = new List(agent.ChannelInstructions);
+ if (instructions.IsNullOrEmpty())
+ {
+ return;
+ }
var state = _services.GetRequiredService();
var channel = state.GetState("channel");
var found = instructions.FirstOrDefault(x => x.Channel.IsEqualTo(channel));
- var defaultInstruction = instructions.FirstOrDefault(x => x.Channel == string.Empty);
+ var defaultInstruction = instructions.FirstOrDefault(x => string.IsNullOrEmpty(x.Channel));
agent.Instruction = !string.IsNullOrWhiteSpace(found?.Instruction) ? found.Instruction : defaultInstruction?.Instruction;
}
- private void PopulateState(Dictionary dict)
+ private void PopulateState(Agent agent)
{
- var conv = _services.GetRequiredService();
- foreach (var t in conv.States.GetStates())
- {
- dict[t.Key] = t.Value;
- }
+ agent.TemplateDict = new(CollectRenderData(agent));
}
private void AddOrUpdateParameters(Agent agent)
{
var agentId = agent.Id ?? agent.Name;
- if (AgentParameterTypes.ContainsKey(agentId)) return;
+ if (AgentParameterTypes.ContainsKey(agentId))
+ {
+ return;
+ }
AddOrUpdateRoutesParameters(agentId, agent.RoutingRules);
AddOrUpdateFunctionsParameters(agentId, agent.Functions);
@@ -103,7 +111,10 @@ private void AddOrUpdateRoutesParameters(string agentId, List routi
foreach (var rule in routingRules.Where(x => x.Required))
{
- if (string.IsNullOrEmpty(rule.FieldType)) continue;
+ if (string.IsNullOrEmpty(rule.FieldType))
+ {
+ continue;
+ }
parameterTypes[rule.Field] = rule.FieldType;
}
}
diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.RefreshAgents.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.RefreshAgents.cs
index cc38a151a..266f69935 100644
--- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.RefreshAgents.cs
+++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.RefreshAgents.cs
@@ -39,7 +39,7 @@ public async Task RefreshAgents(IEnumerable? agentIds = null)
try
{
var agentJson = File.ReadAllText(Path.Combine(dir, "agent.json"));
- var agent = JsonSerializer.Deserialize(agentJson, _options);
+ var agent = JsonSerializer.Deserialize(agentJson, _options.JsonSerializerOptions);
if (agent == null)
{
@@ -62,7 +62,13 @@ public async Task RefreshAgents(IEnumerable? agentIds = null)
var tasks = GetTasksFromFile(dir);
var codeScripts = GetCodeScriptsFromFile(dir);
- var isAgentDeleted = _db.DeleteAgent(agent.Id);
+ var isAgentDeleted = _db.DeleteAgent(agent.Id, options: new()
+ {
+ DeleteRoleAgents = false,
+ DeleteUserAgents = false,
+ ToDeleteCodeScripts = codeScripts
+ });
+
if (isAgentDeleted)
{
await Task.Delay(100);
diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs
index 00f50a1db..83e83ef5a 100644
--- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs
+++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs
@@ -7,7 +7,7 @@ namespace BotSharp.Core.Agents.Services;
public partial class AgentService
{
- public string RenderInstruction(Agent agent, Dictionary? renderData = null)
+ public string RenderInstruction(Agent agent, IDictionary? renderData = null)
{
var render = _services.GetRequiredService();
var conv = _services.GetRequiredService();
@@ -18,16 +18,18 @@ public string RenderInstruction(Agent agent, Dictionary? renderD
instructions.AddRange(secondaryInstructions);
// update states
- var renderDict = renderData != null ? new Dictionary(renderData ?? []) : CollectRenderData(agent);
+ var renderDict = renderData != null
+ ? new Dictionary(renderData)
+ : CollectRenderData(agent);
renderDict[TemplateRenderConstant.RENDER_AGENT] = agent;
var res = render.Render(string.Join("\r\n", instructions), renderDict);
return res;
}
- public bool RenderFunction(Agent agent, FunctionDef def, Dictionary? renderData = null)
+ public bool RenderFunction(Agent agent, FunctionDef def, IDictionary? renderData = null)
{
- var renderDict = renderData ?? agent.TemplateDict;
+ var renderDict = new Dictionary(renderData ?? agent.TemplateDict ?? []);
var isRender = true;
var channels = def.Channels;
@@ -41,7 +43,10 @@ public bool RenderFunction(Agent agent, FunctionDef def, Dictionary? renderData = null)
+ public FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def, IDictionary? renderData = null)
{
- var parameterDef = def?.Parameters;
+ var parameterDef = def?.Parameters?.DeepClone(options: _options);
var propertyDef = parameterDef?.Properties;
- if (propertyDef == null) return null;
+ if (propertyDef == null)
+ {
+ return null;
+ }
- var renderDict = renderData ?? agent.TemplateDict;
+ var renderDict = new Dictionary(renderData ?? agent.TemplateDict ?? []);
var visibleExpress = "visibility_expression";
var root = propertyDef.RootElement;
var iterator = root.EnumerateObject();
@@ -105,7 +113,7 @@ public bool RenderFunction(Agent agent, FunctionDef def, Dictionary) PrepareInstructionAndFunctions(Agent agent, Dictionary? renderData = null, StringComparer ? comparer = null)
+ public (string, IEnumerable) PrepareInstructionAndFunctions(Agent agent, IDictionary? renderData = null, StringComparer ? comparer = null)
{
var text = string.Empty;
if (!string.IsNullOrEmpty(agent.Instruction) || !agent.SecondaryInstructions.IsNullOrEmpty())
@@ -117,7 +125,7 @@ public bool RenderFunction(Agent agent, FunctionDef def, Dictionary? renderData = null)
+ public string RenderTemplate(Agent agent, string templateName, IDictionary? renderData = null)
{
var conv = _services.GetRequiredService();
var render = _services.GetRequiredService();
@@ -125,7 +133,9 @@ public string RenderTemplate(Agent agent, string templateName, Dictionary x.Name == templateName)?.Content ?? string.Empty;
// update states
- var renderDict = renderData != null ? new Dictionary(renderData ?? []) : CollectRenderData(agent);
+ var renderDict = renderData != null
+ ? new Dictionary(renderData)
+ : CollectRenderData(agent);
renderDict[TemplateRenderConstant.RENDER_AGENT] = agent;
// render liquid template
@@ -137,7 +147,7 @@ public string RenderTemplate(Agent agent, string templateName, Dictionary dict)
+ public bool RenderVisibility(string? visibilityExpression, IDictionary dict)
{
if (string.IsNullOrWhiteSpace(visibilityExpression))
{
@@ -145,25 +155,33 @@ public bool RenderVisibility(string? visibilityExpression, Dictionary();
+ var copy = dict != null ? new Dictionary(dict) : [];
var result = render.Render(visibilityExpression, new Dictionary
{
- { "states", dict ?? [] }
+ { "states", copy }
});
return result.IsEqualTo("visible");
}
- public Dictionary CollectRenderData(Agent agent)
+ public IDictionary CollectRenderData(Agent agent)
{
var state = _services.GetRequiredService();
- var renderDict = new Dictionary(agent?.TemplateDict ?? []);
- foreach (var t in state.GetStates())
+ var innerDict = new Dictionary();
+ var dict = new Dictionary(agent.TemplateDict ?? []);
+ foreach (var p in dict)
+ {
+ innerDict[p.Key] = p.Value;
+ }
+
+ var states = new Dictionary(state.GetStates());
+ foreach (var p in states)
{
- renderDict[t.Key] = t.Value;
+ innerDict[p.Key] = p.Value;
}
- return renderDict;
+ return innerDict;
}
#region Private methods
diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs
index ca025447c..d06cc3764 100644
--- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs
+++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs
@@ -1,6 +1,6 @@
+using BotSharp.Abstraction.Options;
using BotSharp.Abstraction.Repositories.Settings;
using System.IO;
-using System.Reflection;
namespace BotSharp.Core.Agents.Services;
@@ -10,24 +10,19 @@ public partial class AgentService : IAgentService
private readonly IBotSharpRepository _db;
private readonly ILogger _logger;
private readonly AgentSettings _agentSettings;
- private readonly JsonSerializerOptions _options;
+ private readonly BotSharpOptions _options;
public AgentService(IServiceProvider services,
IBotSharpRepository db,
ILogger logger,
- AgentSettings agentSettings)
+ AgentSettings agentSettings,
+ BotSharpOptions options)
{
_services = services;
_db = db;
_logger = logger;
_agentSettings = agentSettings;
- _options = new JsonSerializerOptions
- {
- PropertyNameCaseInsensitive = true,
- PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
- WriteIndented = true,
- AllowTrailingCommas = true
- };
+ _options = options;
}
public string GetDataDir()
@@ -49,7 +44,10 @@ public string GetAgentDataDir(string agentId)
public async Task> GetUserAgents(string userId)
{
- if (string.IsNullOrEmpty(userId)) return [];
+ if (string.IsNullOrEmpty(userId))
+ {
+ return [];
+ }
var userAgents = _db.GetUserAgents(userId);
return userAgents;
diff --git a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj
index 8d045f856..d0d517f4a 100644
--- a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj
+++ b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj
@@ -62,50 +62,59 @@
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
@@ -118,129 +127,135 @@
PreserveNewest
-
+
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
PreserveNewest
-
+
+
PreserveNewest
-
+
PreserveNewest
-
+
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
-
-
+
PreserveNewest
-
+
+
PreserveNewest
-
+
PreserveNewest
-
+
+
PreserveNewest
diff --git a/src/Infrastructure/BotSharp.Core/Coding/CodeScriptExecutor.cs b/src/Infrastructure/BotSharp.Core/Coding/CodeScriptExecutor.cs
deleted file mode 100644
index bc38416dc..000000000
--- a/src/Infrastructure/BotSharp.Core/Coding/CodeScriptExecutor.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-namespace BotSharp.Core.Coding;
-
-public class CodeScriptExecutor
-{
- private readonly ILogger _logger;
- private readonly SemaphoreSlim _semLock = new(initialCount: 1, maxCount: 1);
-
- public CodeScriptExecutor(
- ILogger logger)
- {
- _logger = logger;
- }
-
- public async Task ExecuteAsync(Func> func, CancellationToken cancellationToken = default)
- {
- await _semLock.WaitAsync(cancellationToken);
-
- try
- {
- return await func();
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, $"Error in {nameof(CodeScriptExecutor)}.");
- return default(T);
- }
- finally
- {
- _semLock.Release();
- }
- }
-}
diff --git a/src/Infrastructure/BotSharp.Core/Coding/CodingPlugin.cs b/src/Infrastructure/BotSharp.Core/Coding/CodingPlugin.cs
new file mode 100644
index 000000000..efbe13371
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Core/Coding/CodingPlugin.cs
@@ -0,0 +1,17 @@
+using Microsoft.Extensions.Configuration;
+
+namespace BotSharp.Core.Coding;
+
+public class CodingPlugin : IBotSharpPlugin
+{
+ public string Id => "31bc334b-9462-4191-beac-cb4a139b78c1";
+ public string Name => "Coding";
+ public string Description => "Handling execution and generation of code scripts";
+
+ public void RegisterDI(IServiceCollection services, IConfiguration config)
+ {
+ var coding = new CodingSettings();
+ config.Bind("Coding", coding);
+ services.AddSingleton(provider => coding);
+ }
+}
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs b/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs
index e1c44a9a1..6de7da9d6 100644
--- a/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs
+++ b/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs
@@ -69,7 +69,6 @@ public void RegisterDI(IServiceCollection services, IConfiguration config)
services.AddScoped();
services.AddScoped();
- services.AddSingleton();
}
public bool AttachMenu(List menu)
diff --git a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Audio.cs b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Audio.cs
index 62a1356cc..a1cc821e2 100644
--- a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Audio.cs
+++ b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Audio.cs
@@ -9,9 +9,13 @@ public async Task SpeechToText(InstructFileModel audio, string? text = n
if (string.IsNullOrWhiteSpace(text))
{
var innerAgentId = options?.AgentId ?? Guid.Empty.ToString();
- text = await GetAgentTemplate(innerAgentId, options?.TemplateName);
+ text = await RenderAgentTemplate(innerAgentId, options?.TemplateName, options?.Data);
}
-
+ else
+ {
+ text = RenderText(text, options?.Data);
+ }
+
var completion = CompletionProvider.GetAudioTranscriber(_services, provider: options?.Provider, model: options?.Model);
var audioBinary = await DownloadFile(audio);
using var stream = audioBinary.ToStream();
diff --git a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Image.cs b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Image.cs
index dbd9de90f..50e912565 100644
--- a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Image.cs
+++ b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Image.cs
@@ -10,7 +10,8 @@ public partial class FileInstructService
public async Task ReadImages(string text, IEnumerable images, InstructOptions? options = null)
{
var innerAgentId = options?.AgentId ?? Guid.Empty.ToString();
- var instruction = await GetAgentTemplate(innerAgentId, options?.TemplateName);
+ var instruction = await RenderAgentTemplate(innerAgentId, options?.TemplateName, options?.Data);
+ text = RenderText(text, options?.Data);
var completion = CompletionProvider.GetChatCompletion(_services, provider: options?.Provider ?? "openai", model: options?.Model ?? "gpt-4o", multiModal: true);
var message = await completion.GetChatCompletions(new Agent()
@@ -48,7 +49,8 @@ await hook.OnResponseGenerated(new InstructResponseModel
public async Task GenerateImage(string text, InstructOptions? options = null)
{
var innerAgentId = options?.AgentId ?? Guid.Empty.ToString();
- var instruction = await GetAgentTemplate(innerAgentId, options?.TemplateName);
+ var instruction = await RenderAgentTemplate(innerAgentId, options?.TemplateName, options?.Data);
+ text = RenderText(text, options?.Data);
var textContent = text.IfNullOrEmptyAs(instruction).IfNullOrEmptyAs(string.Empty);
var completion = CompletionProvider.GetImageCompletion(_services, provider: options?.Provider ?? "openai", model: options?.Model ?? "gpt-image-1-mini");
@@ -85,7 +87,7 @@ public async Task VaryImage(InstructFileModel image, InstructOp
var binary = await DownloadFile(image);
// Convert image
- var converter = GetImageConverter(options?.ImageConvertProvider);
+ var converter = GetImageConverter(options?.ImageConverter);
if (converter != null)
{
binary = await converter.ConvertImage(binary);
@@ -124,13 +126,14 @@ public async Task EditImage(string text, InstructFileModel imag
}
var innerAgentId = options?.AgentId ?? Guid.Empty.ToString();
- var instruction = await GetAgentTemplate(innerAgentId, options?.TemplateName);
+ var instruction = await RenderAgentTemplate(innerAgentId, options?.TemplateName, options?.Data);
+ text = RenderText(text, options?.Data);
var completion = CompletionProvider.GetImageCompletion(_services, provider: options?.Provider ?? "openai", model: options?.Model ?? "gpt-image-1-mini");
var binary = await DownloadFile(image);
// Convert image
- var converter = GetImageConverter(options?.ImageConvertProvider);
+ var converter = GetImageConverter(options?.ImageConverter);
if (converter != null)
{
binary = await converter.ConvertImage(binary);
@@ -173,14 +176,15 @@ public async Task EditImage(string text, InstructFileModel imag
}
var innerAgentId = options?.AgentId ?? Guid.Empty.ToString();
- var instruction = await GetAgentTemplate(innerAgentId, options?.TemplateName);
+ var instruction = await RenderAgentTemplate(innerAgentId, options?.TemplateName, options?.Data);
+ text = RenderText(text, options?.Data);
var completion = CompletionProvider.GetImageCompletion(_services, provider: options?.Provider ?? "openai", model: options?.Model ?? "gpt-image-1-mini");
var imageBinary = await DownloadFile(image);
var maskBinary = await DownloadFile(mask);
// Convert image
- var converter = GetImageConverter(options?.ImageConvertProvider);
+ var converter = GetImageConverter(options?.ImageConverter);
if (converter != null)
{
imageBinary = await converter.ConvertImage(imageBinary);
@@ -225,7 +229,8 @@ await hook.OnResponseGenerated(new InstructResponseModel
public async Task ComposeImages(string text, InstructFileModel[] images, InstructOptions? options = null)
{
var innerAgentId = options?.AgentId ?? Guid.Empty.ToString();
- var instruction = await GetAgentTemplate(innerAgentId, options?.TemplateName);
+ var instruction = await RenderAgentTemplate(innerAgentId, options?.TemplateName, options?.Data);
+ text = RenderText(text, options?.Data);
var completion = CompletionProvider.GetImageCompletion(_services, provider: options?.Provider ?? "openai", model: options?.Model ?? "gpt-image-1-mini");
@@ -236,7 +241,7 @@ public async Task ComposeImages(string text, InstructFileModel[
var binary = await DownloadFile(image);
// Convert image
- var converter = GetImageConverter(options?.ImageConvertProvider);
+ var converter = GetImageConverter(options?.ImageConverter);
if (converter != null)
{
binary = await converter.ConvertImage(binary);
diff --git a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Pdf.cs b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Pdf.cs
index 2e4792222..bee60f1af 100644
--- a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Pdf.cs
+++ b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Pdf.cs
@@ -26,7 +26,7 @@ public async Task ReadPdf(string text, List files, In
var pdfFiles = await DownloadAndSaveFiles(sessionDir, files);
var targetFiles = pdfFiles;
- var converter = GetImageConverter(options?.ImageConvertProvider);
+ var converter = GetImageConverter(options?.ImageConverter);
if (converter == null && provider == "openai")
{
var fileCoreSettings = _services.GetRequiredService();
@@ -40,7 +40,8 @@ public async Task ReadPdf(string text, List files, In
}
var innerAgentId = options?.AgentId ?? Guid.Empty.ToString();
- var instruction = await GetAgentTemplate(innerAgentId, options?.TemplateName);
+ var instruction = await RenderAgentTemplate(innerAgentId, options?.TemplateName, options?.Data);
+ text = RenderText(text, options?.Data);
var completion = CompletionProvider.GetChatCompletion(_services, provider: provider,
model: options?.Model ?? "gpt-5-mini", multiModal: true);
diff --git a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.cs b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.cs
index 170a0fc0c..48cf5e83c 100644
--- a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.cs
+++ b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.cs
@@ -1,7 +1,6 @@
-
+using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.Files.Converters;
-using Microsoft.Extensions.Options;
-using static System.Net.Mime.MediaTypeNames;
+using BotSharp.Abstraction.Templating;
namespace BotSharp.Core.Files.Services;
@@ -63,7 +62,7 @@ private async Task DownloadFile(InstructFileModel file)
}
}
- private async Task GetAgentTemplate(string agentId, string? templateName)
+ private async Task RenderAgentTemplate(string agentId, string? templateName, IDictionary? data = null)
{
if (string.IsNullOrWhiteSpace(agentId) || string.IsNullOrWhiteSpace(templateName))
{
@@ -77,21 +76,32 @@ private async Task DownloadFile(InstructFileModel file)
return null;
}
- var instruction = agentService.RenderTemplate(agent, templateName);
+ var instruction = agentService.RenderTemplate(agent, templateName, data);
return instruction;
}
+ private string RenderText(string text, IDictionary? data = null)
+ {
+ var agentService = _services.GetRequiredService();
+ var render = _services.GetRequiredService();
+
+ var renderData = data != null
+ ? new Dictionary(data)
+ : agentService.CollectRenderData(new Agent());
+ return render.Render(text, renderData);
+ }
+
private string BuildFileName(string? name, string? extension, string defaultName, string defaultExtension)
{
var fname = name.IfNullOrEmptyAs(defaultName);
- var fextension = extension.IfNullOrEmptyAs(defaultExtension);
+ var fextension = extension.IfNullOrEmptyAs(defaultExtension)!;
fextension = fextension.StartsWith(".") ? fextension.Substring(1) : fextension;
return $"{name}.{fextension}";
}
private IImageConverter? GetImageConverter(string? provider)
{
- var converter = _services.GetServices().FirstOrDefault(x => x.Provider == (provider ?? "file-handler"));
+ var converter = _services.GetServices().FirstOrDefault(x => x.Provider == (provider ?? "image-handler"));
return converter;
}
#endregion
diff --git a/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.Audio.cs b/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.Audio.cs
index a62744a51..0cd8a8c70 100644
--- a/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.Audio.cs
+++ b/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.Audio.cs
@@ -15,7 +15,10 @@ public bool SaveSpeechFile(string conversationId, string fileName, BinaryData da
}
var filePath = Path.Combine(dir, fileName);
- if (File.Exists(filePath)) return false;
+ if (File.Exists(filePath))
+ {
+ return false;
+ }
using var fs = File.Create(filePath);
using var ds = data.ToStream();
diff --git a/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.Common.cs b/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.Common.cs
index 80a10deeb..afed03f54 100644
--- a/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.Common.cs
+++ b/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.Common.cs
@@ -40,7 +40,10 @@ public BinaryData GetFileBytes(string fileStorageUrl)
public bool SaveFileStreamToPath(string filePath, Stream stream)
{
- if (string.IsNullOrEmpty(filePath)) return false;
+ if (string.IsNullOrEmpty(filePath))
+ {
+ return false;
+ }
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
diff --git a/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.Conversation.cs b/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.Conversation.cs
index e4f5fc5c9..23135e8c9 100644
--- a/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.Conversation.cs
+++ b/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.Conversation.cs
@@ -34,9 +34,9 @@ public async Task> GetMessageFileScreenshotsAsync(
continue;
}
- foreach (var subDir in Directory.GetDirectories(dir))
+ foreach (var subDir in Directory.EnumerateDirectories(dir))
{
- var file = Directory.GetFiles(subDir).FirstOrDefault();
+ var file = Directory.EnumerateFiles(subDir).FirstOrDefault();
if (file == null)
{
continue;
@@ -79,7 +79,7 @@ public IEnumerable GetMessageFiles(string conversationId, IEnu
var sources = options?.Sources != null
? options.Sources
- : Directory.GetDirectories(baseDir).Select(x => x.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries).Last());
+ : Directory.EnumerateDirectories(baseDir).Select(x => x.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries).Last());
if (sources.IsNullOrEmpty())
{
continue;
@@ -93,11 +93,11 @@ public IEnumerable GetMessageFiles(string conversationId, IEnu
continue;
}
- foreach (var subDir in Directory.GetDirectories(dir))
+ foreach (var subDir in Directory.EnumerateDirectories(dir))
{
var fileIndex = subDir.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries).Last();
- foreach (var file in Directory.GetFiles(subDir))
+ foreach (var file in Directory.EnumerateFiles(subDir))
{
var contentType = FileUtility.GetFileContentType(file);
if (options?.ContentTypes != null && !options.ContentTypes.Contains(contentType))
@@ -143,7 +143,7 @@ public string GetMessageFile(string conversationId, string messageId, string sou
return string.Empty;
}
- var found = Directory.GetFiles(dir).FirstOrDefault(f => Path.GetFileNameWithoutExtension(f).IsEqualTo(fileName));
+ var found = Directory.EnumerateFiles(dir).FirstOrDefault(f => Path.GetFileNameWithoutExtension(f).IsEqualTo(fileName));
return found;
}
@@ -308,9 +308,9 @@ private async Task> GetScreenshotsAsync(string fil
var contentType = FileUtility.GetFileContentType(file);
var screenshotDir = Path.Combine(parentDir, SCREENSHOT_FILE_FOLDER);
- if (ExistDirectory(screenshotDir) && !Directory.GetFiles(screenshotDir).IsNullOrEmpty())
+ if (ExistDirectory(screenshotDir))
{
- foreach (var screenshot in Directory.GetFiles(screenshotDir))
+ foreach (var screenshot in Directory.EnumerateFiles(screenshotDir))
{
var fileName = Path.GetFileNameWithoutExtension(screenshot);
var fileExtension = Path.GetExtension(screenshot).Substring(1);
diff --git a/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.KnowledgeBase.cs b/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.KnowledgeBase.cs
index 8fc6bb0ac..72170fea0 100644
--- a/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.KnowledgeBase.cs
+++ b/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.KnowledgeBase.cs
@@ -46,7 +46,10 @@ public bool DeleteKnowledgeFile(string collectionName, string vectorStoreProvide
}
var dir = BuildKnowledgeCollectionFileDir(collectionName, vectorStoreProvider);
- if (!ExistDirectory(dir)) return false;
+ if (!ExistDirectory(dir))
+ {
+ return false;
+ }
if (fileId == null)
{
diff --git a/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.User.cs b/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.User.cs
index 9384bd837..6935a1ad2 100644
--- a/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.User.cs
+++ b/src/Infrastructure/BotSharp.Core/Files/Services/Storage/LocalFileStorageService.User.cs
@@ -10,7 +10,10 @@ public string GetUserAvatar()
var user = db.GetUserById(_user.Id);
var dir = GetUserAvatarDir(user?.Id);
- if (!ExistDirectory(dir)) return string.Empty;
+ if (!ExistDirectory(dir))
+ {
+ return string.Empty;
+ }
var found = Directory.GetFiles(dir).FirstOrDefault() ?? string.Empty;
return found;
@@ -18,7 +21,10 @@ public string GetUserAvatar()
public bool SaveUserAvatar(FileDataModel file)
{
- if (file == null || string.IsNullOrEmpty(file.FileData)) return false;
+ if (file == null || string.IsNullOrEmpty(file.FileData))
+ {
+ return false;
+ }
try
{
@@ -26,7 +32,10 @@ public bool SaveUserAvatar(FileDataModel file)
var user = db.GetUserById(_user.Id);
var dir = GetUserAvatarDir(user?.Id);
- if (string.IsNullOrEmpty(dir)) return false;
+ if (string.IsNullOrEmpty(dir))
+ {
+ return false;
+ }
if (Directory.Exists(dir))
{
diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/CompletionProvider.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/CompletionProvider.cs
index 60645bcf2..b5d989298 100644
--- a/src/Infrastructure/BotSharp.Core/Infrastructures/CompletionProvider.cs
+++ b/src/Infrastructure/BotSharp.Core/Infrastructures/CompletionProvider.cs
@@ -5,7 +5,8 @@ namespace BotSharp.Core.Infrastructures;
public class CompletionProvider
{
- public static object GetCompletion(IServiceProvider services,
+ public static object GetCompletion(
+ IServiceProvider services,
string? provider = null,
string? model = null,
AgentLlmConfig? agentConfig = null)
@@ -42,7 +43,8 @@ public static object GetCompletion(IServiceProvider services,
}
}
- public static IChatCompletion GetChatCompletion(IServiceProvider services,
+ public static IChatCompletion GetChatCompletion(
+ IServiceProvider services,
string? provider = null,
string? model = null,
string? modelId = null,
@@ -66,7 +68,8 @@ public static IChatCompletion GetChatCompletion(IServiceProvider services,
return completer;
}
- public static ITextCompletion GetTextCompletion(IServiceProvider services,
+ public static ITextCompletion GetTextCompletion(
+ IServiceProvider services,
string? provider = null,
string? model = null,
AgentLlmConfig? agentConfig = null)
@@ -86,15 +89,16 @@ public static ITextCompletion GetTextCompletion(IServiceProvider services,
return completer;
}
- public static IImageCompletion GetImageCompletion(IServiceProvider services,
+ public static IImageCompletion GetImageCompletion(
+ IServiceProvider services,
string? provider = null,
string? model = null,
string? modelId = null,
- bool imageGenerate = false)
+ IEnumerable? capabilities = null)
{
var completions = services.GetServices();
(provider, model) = GetProviderAndModel(services, provider: provider,
- model: model, modelId: modelId, imageGenerate: imageGenerate);
+ model: model, modelId: modelId, capabilities: capabilities);
var completer = completions.FirstOrDefault(x => x.Provider == provider);
if (completer == null)
@@ -107,7 +111,8 @@ public static IImageCompletion GetImageCompletion(IServiceProvider services,
return completer;
}
- public static ITextEmbedding GetTextEmbedding(IServiceProvider services,
+ public static ITextEmbedding GetTextEmbedding(
+ IServiceProvider services,
string? provider = null,
string? model = null)
{
@@ -166,7 +171,8 @@ public static IAudioSynthesis GetAudioSynthesizer(
return completer;
}
- public static IRealTimeCompletion GetRealTimeCompletion(IServiceProvider services,
+ public static IRealTimeCompletion GetRealTimeCompletion(
+ IServiceProvider services,
string? provider = null,
string? model = null,
string? modelId = null,
@@ -176,7 +182,7 @@ public static IRealTimeCompletion GetRealTimeCompletion(IServiceProvider service
var completions = services.GetServices();
(provider, model) = GetProviderAndModel(services, provider: provider, model: model, modelId: modelId,
multiModal: multiModal,
- modelType: LlmModelType.Realtime,
+ modelType: LlmModelType.Realtime,
agentConfig: agentConfig);
var completer = completions.FirstOrDefault(x => x.Provider == provider);
@@ -190,13 +196,14 @@ public static IRealTimeCompletion GetRealTimeCompletion(IServiceProvider service
return completer;
}
- private static (string, string) GetProviderAndModel(IServiceProvider services,
+ private static (string, string) GetProviderAndModel(
+ IServiceProvider services,
string? provider = null,
string? model = null,
string? modelId = null,
bool? multiModal = null,
LlmModelType? modelType = null,
- bool imageGenerate = false,
+ IEnumerable? capabilities = null,
AgentLlmConfig? agentConfig = null)
{
var agentSetting = services.GetRequiredService();
@@ -220,9 +227,9 @@ private static (string, string) GetProviderAndModel(IServiceProvider services,
var modelIdentity = state.ContainsState("model_id") ? state.GetState("model_id") : modelId;
var llmProviderService = services.GetRequiredService();
model = llmProviderService.GetProviderModel(provider, modelIdentity,
- multiModal: multiModal,
+ multiModal: multiModal,
modelType: modelType,
- imageGenerate: imageGenerate)?.Name;
+ capabilities: capabilities)?.Name;
}
}
diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/HookEmitter.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/HookEmitter.cs
index 3615faf52..66ce90446 100644
--- a/src/Infrastructure/BotSharp.Core/Infrastructures/HookEmitter.cs
+++ b/src/Infrastructure/BotSharp.Core/Infrastructures/HookEmitter.cs
@@ -1,4 +1,3 @@
-using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Infrastructures;
namespace BotSharp.Core.Infrastructures;
diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/LlmProviderService.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/LlmProviderService.cs
index 95cfd9c04..3445d3c00 100644
--- a/src/Infrastructure/BotSharp.Core/Infrastructures/LlmProviderService.cs
+++ b/src/Infrastructure/BotSharp.Core/Infrastructures/LlmProviderService.cs
@@ -1,4 +1,5 @@
using BotSharp.Abstraction.MLTasks;
+using BotSharp.Abstraction.MLTasks.Filters;
using BotSharp.Abstraction.MLTasks.Settings;
using BotSharp.Abstraction.Settings;
@@ -40,14 +41,12 @@ public List GetProviderModels(string provider)
{
var settingService = _services.GetRequiredService();
return settingService.Bind>($"LlmProviders")
- .FirstOrDefault(x => x.Provider.Equals(provider))
- ?.Models ?? new List