refine repository for agent code script
This commit is contained in:
parent
74d0c96e2f
commit
5be85d3f4b
|
|
@ -0,0 +1,7 @@
|
|||
namespace BotSharp.Abstraction.Agents.Enums;
|
||||
|
||||
public static class AgentCodeScriptType
|
||||
{
|
||||
public const string Src = "src";
|
||||
public const string Test = "test";
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Agents.Enums;
|
||||
|
||||
public class AgentFuncVisMode
|
||||
public static class AgentFuncVisMode
|
||||
{
|
||||
public const string Manual = "manual";
|
||||
public const string Auto = "auto";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Agents.Enums;
|
||||
|
||||
public class AgentRole
|
||||
public static class AgentRole
|
||||
{
|
||||
public const string System = "system";
|
||||
public const string Assistant = "assistant";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Agents.Enums;
|
||||
|
||||
public class AgentType
|
||||
public static class AgentType
|
||||
{
|
||||
/// <summary>
|
||||
/// Routing agent
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Agents.Enums;
|
||||
|
||||
public class BuiltInAgentId
|
||||
public static class BuiltInAgentId
|
||||
{
|
||||
/// <summary>
|
||||
/// A routing agent can be used as a base router.
|
||||
|
|
|
|||
|
|
@ -1,18 +1,29 @@
|
|||
namespace BotSharp.Abstraction.Agents.Models;
|
||||
|
||||
public class AgentCodeScript
|
||||
public class AgentCodeScript : AgentCodeScriptBase
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string AgentId { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Content { get; set; }
|
||||
public string AgentId { get; set; } = null!;
|
||||
|
||||
public AgentCodeScript()
|
||||
public AgentCodeScript() : base()
|
||||
{
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
return $"{CodePath}";
|
||||
}
|
||||
}
|
||||
|
||||
public class AgentCodeScriptBase
|
||||
{
|
||||
public string Name { get; set; } = null!;
|
||||
public string Content { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Code script type: src, test
|
||||
/// </summary>
|
||||
public string ScriptType { get; set; } = null!;
|
||||
|
||||
public string CodePath => $"{ScriptType}/{Name}";
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Conversations.Enums;
|
||||
|
||||
public class ConversationChannel
|
||||
public static class ConversationChannel
|
||||
{
|
||||
public const string WebChat = "webchat";
|
||||
public const string OpenAPI = "openapi";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Conversations.Enums;
|
||||
|
||||
public class ConversationStatus
|
||||
public static class ConversationStatus
|
||||
{
|
||||
public const string Open = "open";
|
||||
public const string Closed = "closed";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Conversations.Enums;
|
||||
|
||||
public class StateDataType
|
||||
public static class StateDataType
|
||||
{
|
||||
public const string String = "string";
|
||||
public const string Boolean = "boolean";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Conversations.Enums;
|
||||
|
||||
public class StateSource
|
||||
public static class StateSource
|
||||
{
|
||||
public const string External = "external";
|
||||
public const string Application = "application";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Infrastructures.Enums;
|
||||
|
||||
public class LanguageType
|
||||
public static class LanguageType
|
||||
{
|
||||
public const string UNKNOWN = "Unknown";
|
||||
public const string ENGLISH = "English";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Infrastructures.Enums;
|
||||
|
||||
public class StateConst
|
||||
public static class StateConst
|
||||
{
|
||||
public const string EXPECTED_ACTION_AGENT = "expected_next_action_agent";
|
||||
public const string EXPECTED_GOAL_AGENT = "expected_user_goal_agent";
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ namespace BotSharp.Abstraction.Instructs;
|
|||
|
||||
public interface IInstructHook : IHookBase
|
||||
{
|
||||
Task BeforeCompletion(Agent agent, RoleDialogModel message);
|
||||
Task AfterCompletion(Agent agent, InstructResult result);
|
||||
Task OnResponseGenerated(InstructResponseModel response);
|
||||
Task BeforeCompletion(Agent agent, RoleDialogModel message) => Task.CompletedTask;
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Instructs.Models;
|
||||
|
||||
public class CodeInstructContext
|
||||
{
|
||||
public List<KeyValue> Arguments { get; set; } = [];
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
namespace BotSharp.Abstraction.Repositories.Filters;
|
||||
|
||||
public class AgentCodeScriptFilter
|
||||
{
|
||||
public List<string>? ScriptNames { get; set; }
|
||||
public List<string>? ScriptTypes { get; set; }
|
||||
|
||||
public static AgentCodeScriptFilter Empty()
|
||||
{
|
||||
return new AgentCodeScriptFilter();
|
||||
}
|
||||
}
|
||||
|
|
@ -107,15 +107,15 @@ public interface IBotSharpRepository : IHaveServiceProvider
|
|||
#endregion
|
||||
|
||||
#region Agent Code
|
||||
List<AgentCodeScript> GetAgentCodeScripts(string agentId, List<string>? scriptNames = null)
|
||||
List<AgentCodeScript> GetAgentCodeScripts(string agentId, AgentCodeScriptFilter? filter = null)
|
||||
=> throw new NotImplementedException();
|
||||
string? GetAgentCodeScript(string agentId, string scriptName)
|
||||
string? GetAgentCodeScript(string agentId, string scriptName, string scriptType = AgentCodeScriptType.Src)
|
||||
=> throw new NotImplementedException();
|
||||
bool UpdateAgentCodeScripts(string agentId, List<AgentCodeScript> scripts)
|
||||
=> throw new NotImplementedException();
|
||||
bool BulkInsertAgentCodeScripts(string agentId, List<AgentCodeScript> scripts)
|
||||
=> throw new NotImplementedException();
|
||||
bool DeleteAgentCodeScripts(string agentId, List<string>? scriptNames)
|
||||
bool DeleteAgentCodeScripts(string agentId, List<AgentCodeScript>? scripts = null)
|
||||
=> throw new NotImplementedException();
|
||||
#endregion
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Routing.Enums;
|
||||
|
||||
public class RoutingMode
|
||||
public static class RoutingMode
|
||||
{
|
||||
public const string Eager = "eager";
|
||||
public const string Lazy = "lazy";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Routing.Enums;
|
||||
|
||||
public class RuleType
|
||||
public static class RuleType
|
||||
{
|
||||
/// <summary>
|
||||
/// Fallback to redirect agent
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/// <summary>
|
||||
/// Agent task status
|
||||
/// </summary>
|
||||
public class TaskStatus
|
||||
public static class TaskStatus
|
||||
{
|
||||
public const string Scheduled = "scheduled";
|
||||
public const string New = "new";
|
||||
|
|
|
|||
|
|
@ -229,12 +229,22 @@ public partial class AgentService
|
|||
}
|
||||
|
||||
var agentId = fileDir.Split(Path.DirectorySeparatorChar).Last();
|
||||
scripts = Directory.GetFiles(codeDir).Select(file => new AgentCodeScript
|
||||
|
||||
foreach (var folder in Directory.EnumerateDirectories(codeDir))
|
||||
{
|
||||
var scriptType = folder.Split(Path.DirectorySeparatorChar).Last();
|
||||
foreach (var file in Directory.EnumerateFiles(folder))
|
||||
{
|
||||
scripts.Add(new AgentCodeScript
|
||||
{
|
||||
AgentId = agentId,
|
||||
Name = Path.GetFileName(file),
|
||||
ScriptType = scriptType,
|
||||
Content = File.ReadAllText(file)
|
||||
}).ToList();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return scripts;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,9 +40,12 @@ public partial class InstructService
|
|||
}
|
||||
|
||||
|
||||
var provider = string.Empty;
|
||||
var model = string.Empty;
|
||||
var prompt = string.Empty;
|
||||
// Run code template
|
||||
var codeResponse = await GetCodeResponse(agent, message, templateName, codeOptions);
|
||||
if (codeResponse != null)
|
||||
{
|
||||
return codeResponse;
|
||||
}
|
||||
|
||||
|
||||
// Before completion hooks
|
||||
|
|
@ -63,16 +66,11 @@ public partial class InstructService
|
|||
}
|
||||
|
||||
|
||||
// Run code template
|
||||
var (text, isCodeComplete) = await GetCodeResponse(agentId, templateName, codeOptions);
|
||||
if (isCodeComplete)
|
||||
{
|
||||
response.Text = text;
|
||||
}
|
||||
else
|
||||
{
|
||||
var provider = string.Empty;
|
||||
var model = string.Empty;
|
||||
|
||||
// Render prompt
|
||||
prompt = string.IsNullOrEmpty(templateName) ?
|
||||
var prompt = string.IsNullOrEmpty(templateName) ?
|
||||
agentService.RenderInstruction(agent) :
|
||||
agentService.RenderTemplate(agent, templateName);
|
||||
|
||||
|
|
@ -115,14 +113,11 @@ public partial class InstructService
|
|||
});
|
||||
response.Text = result.Content;
|
||||
}
|
||||
}
|
||||
|
||||
// After completion hooks
|
||||
foreach (var hook in hooks)
|
||||
{
|
||||
await hook.AfterCompletion(agent, response);
|
||||
if (!isCodeComplete)
|
||||
{
|
||||
await hook.OnResponseGenerated(new InstructResponseModel
|
||||
{
|
||||
AgentId = agentId,
|
||||
|
|
@ -134,25 +129,31 @@ public partial class InstructService
|
|||
CompletionText = response.Text
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get code response => return: (response text, whether code execution is completed)
|
||||
/// Get code response
|
||||
/// </summary>
|
||||
/// <param name="agentId"></param>
|
||||
/// <param name="agent"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="templateName"></param>
|
||||
/// <param name="codeOptions"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<(string?, bool)> GetCodeResponse(string agentId, string templateName, CodeInstructOptions? codeOptions)
|
||||
private async Task<InstructResult?> GetCodeResponse(Agent agent, RoleDialogModel message, string templateName, CodeInstructOptions? codeOptions)
|
||||
{
|
||||
InstructResult? response = null;
|
||||
|
||||
if (agent == null)
|
||||
{
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
var state = _services.GetRequiredService<IConversationStateService>();
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
|
||||
var isComplete = false;
|
||||
var response = string.Empty;
|
||||
var hooks = _services.GetHooks<IInstructHook>(agent.Id);
|
||||
|
||||
var codeProvider = codeOptions?.CodeInterpretProvider.IfNullOrEmptyAs("botsharp-py-interpreter");
|
||||
var codeInterpreter = _services.GetServices<ICodeInterpretService>()
|
||||
|
|
@ -161,9 +162,9 @@ public partial class InstructService
|
|||
if (codeInterpreter == null)
|
||||
{
|
||||
#if DEBUG
|
||||
_logger.LogWarning($"No code interpreter found. (Agent: {agentId}, Code interpreter: {codeProvider})");
|
||||
_logger.LogWarning($"No code interpreter found. (Agent: {agent.Id}, Code interpreter: {codeProvider})");
|
||||
#endif
|
||||
return (response, isComplete);
|
||||
return response;
|
||||
}
|
||||
|
||||
// Get code script name
|
||||
|
|
@ -180,19 +181,19 @@ public partial class InstructService
|
|||
if (string.IsNullOrEmpty(scriptName))
|
||||
{
|
||||
#if DEBUG
|
||||
_logger.LogWarning($"Empty code script name. (Agent: {agentId}, {scriptName})");
|
||||
_logger.LogWarning($"Empty code script name. (Agent: {agent.Id}, {scriptName})");
|
||||
#endif
|
||||
return (response, isComplete);
|
||||
return response;
|
||||
}
|
||||
|
||||
// Get code script
|
||||
var codeScript = db.GetAgentCodeScript(agentId, scriptName);
|
||||
var codeScript = db.GetAgentCodeScript(agent.Id, scriptName, scriptType: AgentCodeScriptType.Src);
|
||||
if (string.IsNullOrWhiteSpace(codeScript))
|
||||
{
|
||||
#if DEBUG
|
||||
_logger.LogWarning($"Empty code script. (Agent: {agentId}, {scriptName})");
|
||||
_logger.LogWarning($"Empty code script. (Agent: {agent.Id}, {scriptName})");
|
||||
#endif
|
||||
return (response, isComplete);
|
||||
return response;
|
||||
}
|
||||
|
||||
// Get code arguments
|
||||
|
|
@ -202,14 +203,55 @@ public partial class InstructService
|
|||
arguments = state.GetStates().Select(x => new KeyValue(x.Key, x.Value)).ToList();
|
||||
}
|
||||
|
||||
var context = new CodeInstructContext
|
||||
{
|
||||
Arguments = arguments
|
||||
};
|
||||
|
||||
// Before code execution
|
||||
foreach (var hook in hooks)
|
||||
{
|
||||
await hook.BeforeCodeExecution(agent, message, context);
|
||||
|
||||
// Interrupted by hook
|
||||
if (message.StopCompletion)
|
||||
{
|
||||
return new InstructResult
|
||||
{
|
||||
MessageId = message.MessageId,
|
||||
Text = message.Content
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Run code script
|
||||
var result = await codeInterpreter.RunCode(codeScript, options: new()
|
||||
{
|
||||
Arguments = arguments
|
||||
Arguments = context.Arguments
|
||||
});
|
||||
|
||||
response = result?.Result?.ToString();
|
||||
isComplete = true;
|
||||
return (response, isComplete);
|
||||
response = new InstructResult
|
||||
{
|
||||
MessageId = message.MessageId,
|
||||
Text = result?.Result?.ToString()
|
||||
};
|
||||
|
||||
// After code execution
|
||||
foreach (var hook in hooks)
|
||||
{
|
||||
await hook.AfterCodeExecution(agent, response);
|
||||
await hook.OnResponseGenerated(new InstructResponseModel
|
||||
{
|
||||
AgentId = agent.Id,
|
||||
Provider = codeInterpreter.Provider,
|
||||
Model = string.Empty,
|
||||
TemplateName = scriptName,
|
||||
UserMessage = string.Empty,
|
||||
SystemInstruction = string.Empty,
|
||||
CompletionText = response.Text
|
||||
});
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,161 +0,0 @@
|
|||
using System.IO;
|
||||
|
||||
namespace BotSharp.Core.Repository;
|
||||
|
||||
public partial class FileRepository
|
||||
{
|
||||
#region Code
|
||||
public List<AgentCodeScript> GetAgentCodeScripts(string agentId, List<string>? scriptNames = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId))
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
var dir = BuildAgentCodeDir(agentId);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
var results = new List<AgentCodeScript>();
|
||||
foreach (var file in Directory.GetFiles(dir))
|
||||
{
|
||||
var fileName = Path.GetFileName(file);
|
||||
if (scriptNames != null && !scriptNames.Contains(fileName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var script = new AgentCodeScript
|
||||
{
|
||||
AgentId = agentId,
|
||||
Name = fileName,
|
||||
Content = File.ReadAllText(file)
|
||||
};
|
||||
results.Add(script);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public string? GetAgentCodeScript(string agentId, string scriptName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId)
|
||||
|| string.IsNullOrWhiteSpace(scriptName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var dir = BuildAgentCodeDir(agentId);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (var file in Directory.GetFiles(dir))
|
||||
{
|
||||
var fileName = Path.GetFileName(file);
|
||||
if (scriptName.IsEqualTo(fileName))
|
||||
{
|
||||
return File.ReadAllText(file);
|
||||
}
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public bool UpdateAgentCodeScripts(string agentId, List<AgentCodeScript> scripts)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId) || scripts.IsNullOrEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var dir = BuildAgentCodeDir(agentId);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var dict = scripts.DistinctBy(x => x.Name).ToDictionary(x => x.Name, x => x);
|
||||
var files = Directory.GetFiles(dir).Where(x => dict.Keys.Contains(Path.GetFileName(x))).ToList();
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
if (dict.TryGetValue(Path.GetFileName(file), out var script))
|
||||
{
|
||||
File.WriteAllText(file, script.Content);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool BulkInsertAgentCodeScripts(string agentId, List<AgentCodeScript> scripts)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId) || scripts.IsNullOrEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var dir = BuildAgentCodeDir(agentId);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var script in scripts)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(script.Name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var path = Path.Combine(dir, script.Name);
|
||||
File.WriteAllText(path, script.Content);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DeleteAgentCodeScripts(string agentId, List<string>? scriptNames)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var dir = BuildAgentCodeDir(agentId);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (scriptNames == null)
|
||||
{
|
||||
Directory.Delete(dir, true);
|
||||
return true;
|
||||
}
|
||||
else if (!scriptNames.Any())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var file in Directory.GetFiles(dir))
|
||||
{
|
||||
var fileName = Path.GetFileName(file);
|
||||
if (scriptNames.Contains(fileName))
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
private string BuildAgentCodeDir(string agentId)
|
||||
{
|
||||
return Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, AGENT_CODES_FOLDER);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
using System.IO;
|
||||
|
||||
namespace BotSharp.Core.Repository;
|
||||
|
||||
public partial class FileRepository
|
||||
{
|
||||
#region Code
|
||||
public List<AgentCodeScript> GetAgentCodeScripts(string agentId, AgentCodeScriptFilter? filter = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId))
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
var dir = BuildAgentCodeScriptDir(agentId);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
filter ??= AgentCodeScriptFilter.Empty();
|
||||
var results = new List<AgentCodeScript>();
|
||||
|
||||
foreach (var folder in Directory.EnumerateDirectories(dir))
|
||||
{
|
||||
var scriptType = folder.Split(Path.DirectorySeparatorChar).Last();
|
||||
if (filter.ScriptTypes != null && !filter.ScriptTypes.Contains(scriptType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(folder))
|
||||
{
|
||||
var fileName = Path.GetFileName(file);
|
||||
if (filter.ScriptNames != null && !filter.ScriptNames.Contains(fileName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
results.Add(new AgentCodeScript
|
||||
{
|
||||
AgentId = agentId,
|
||||
Name = fileName,
|
||||
ScriptType = scriptType,
|
||||
Content = File.ReadAllText(file)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public string? GetAgentCodeScript(string agentId, string scriptName, string scriptType = AgentCodeScriptType.Src)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId)
|
||||
|| string.IsNullOrWhiteSpace(scriptName)
|
||||
|| string.IsNullOrWhiteSpace(scriptType))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var dir = BuildAgentCodeScriptDir(agentId, scriptType);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var foundFile = Directory.GetFiles(dir).FirstOrDefault(file => scriptName.IsEqualTo(Path.GetFileName(file)));
|
||||
if (!string.IsNullOrEmpty(foundFile))
|
||||
{
|
||||
return File.ReadAllText(foundFile);
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public bool UpdateAgentCodeScripts(string agentId, List<AgentCodeScript> scripts)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId) || scripts.IsNullOrEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var script in scripts)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(script.Name)
|
||||
|| string.IsNullOrWhiteSpace(script.ScriptType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var dir = BuildAgentCodeScriptDir(agentId, script.ScriptType);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var file = Path.Combine(dir, script.Name);
|
||||
File.WriteAllText(file, script.Content);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool BulkInsertAgentCodeScripts(string agentId, List<AgentCodeScript> scripts)
|
||||
{
|
||||
return UpdateAgentCodeScripts(agentId, scripts);
|
||||
}
|
||||
|
||||
public bool DeleteAgentCodeScripts(string agentId, List<AgentCodeScript>? scripts = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var dir = BuildAgentCodeScriptDir(agentId);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (scripts == null)
|
||||
{
|
||||
Directory.Delete(dir, true);
|
||||
return true;
|
||||
}
|
||||
else if (!scripts.Any())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var dict = scripts.DistinctBy(x => x.CodePath).ToDictionary(x => x.CodePath, x => x);
|
||||
foreach (var pair in dict)
|
||||
{
|
||||
var file = Path.Combine(dir, pair.Value.ScriptType, pair.Value.Name);
|
||||
if (File.Exists(file))
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
private string BuildAgentCodeScriptDir(string agentId, string? scirptType = null)
|
||||
{
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, AGENT_CODES_FOLDER);
|
||||
if (!string.IsNullOrWhiteSpace(scirptType))
|
||||
{
|
||||
dir = Path.Combine(dir, scirptType);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ using BotSharp.Abstraction.Instructs.Models;
|
|||
using BotSharp.Abstraction.Instructs.Settings;
|
||||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Users;
|
||||
using BotSharp.Abstraction.Utilities;
|
||||
|
||||
namespace BotSharp.Logger.Hooks;
|
||||
|
||||
|
|
@ -39,7 +40,9 @@ public class InstructionLogHook : InstructHookBase
|
|||
var state = _services.GetRequiredService<IConversationStateService>();
|
||||
|
||||
var user = db.GetUserById(_user.Id);
|
||||
var templateName = response.TemplateName ?? state.GetState("instruct_template_name") ?? null;
|
||||
var templateName = response.TemplateName
|
||||
.IfNullOrEmptyAs(state.GetState("instruct_template_name"))
|
||||
.IfNullOrEmptyAs(null);
|
||||
|
||||
db.SaveInstructionLogs(new List<InstructionLogModel>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,31 +2,34 @@ using BotSharp.Abstraction.Agents.Models;
|
|||
|
||||
namespace BotSharp.Plugin.MongoStorage.Collections;
|
||||
|
||||
public class AgentCodeDocument : MongoBase
|
||||
public class AgentCodeScriptDocument : MongoBase
|
||||
{
|
||||
public string AgentId { get; set; } = default!;
|
||||
public string Name { get; set; } = default!;
|
||||
public string Content { get; set; } = default!;
|
||||
public string ScriptType { get; set; } = default!;
|
||||
|
||||
public static AgentCodeDocument ToMongoModel(AgentCodeScript script)
|
||||
public static AgentCodeScriptDocument ToMongoModel(AgentCodeScript script)
|
||||
{
|
||||
return new AgentCodeDocument
|
||||
return new AgentCodeScriptDocument
|
||||
{
|
||||
Id = script.Id,
|
||||
AgentId = script.AgentId,
|
||||
Name = script.Name,
|
||||
Content = script.Content
|
||||
Content = script.Content,
|
||||
ScriptType = script.ScriptType
|
||||
};
|
||||
}
|
||||
|
||||
public static AgentCodeScript ToDomainModel(AgentCodeDocument script)
|
||||
public static AgentCodeScript ToDomainModel(AgentCodeScriptDocument script)
|
||||
{
|
||||
return new AgentCodeScript
|
||||
{
|
||||
Id = script.Id,
|
||||
AgentId = script.AgentId,
|
||||
Name = script.Name,
|
||||
Content = script.Content
|
||||
Content = script.Content,
|
||||
ScriptType = script.ScriptType
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -160,8 +160,8 @@ public class MongoDbContext
|
|||
public IMongoCollection<AgentTaskDocument> AgentTasks
|
||||
=> CreateAgentTaskIndex();
|
||||
|
||||
public IMongoCollection<AgentCodeDocument> AgentCodes
|
||||
=> GetCollectionOrCreate<AgentCodeDocument>("AgentCodes");
|
||||
public IMongoCollection<AgentCodeScriptDocument> AgentCodeScripts
|
||||
=> GetCollectionOrCreate<AgentCodeScriptDocument>("AgentCodeScripts");
|
||||
|
||||
public IMongoCollection<ConversationDocument> Conversations
|
||||
=> CreateConversationIndex();
|
||||
|
|
|
|||
|
|
@ -594,7 +594,7 @@ public partial class MongoRepository
|
|||
_dc.UserAgents.DeleteMany(Builders<UserAgentDocument>.Filter.Empty);
|
||||
_dc.RoleAgents.DeleteMany(Builders<RoleAgentDocument>.Filter.Empty);
|
||||
_dc.AgentTasks.DeleteMany(Builders<AgentTaskDocument>.Filter.Empty);
|
||||
_dc.AgentCodes.DeleteMany(Builders<AgentCodeDocument>.Filter.Empty);
|
||||
_dc.AgentCodeScripts.DeleteMany(Builders<AgentCodeScriptDocument>.Filter.Empty);
|
||||
_dc.Agents.DeleteMany(Builders<AgentDocument>.Filter.Empty);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -614,12 +614,12 @@ public partial class MongoRepository
|
|||
var userAgentFilter = Builders<UserAgentDocument>.Filter.Eq(x => x.AgentId, agentId);
|
||||
var roleAgentFilter = Builders<RoleAgentDocument>.Filter.Eq(x => x.AgentId, agentId);
|
||||
var agentTaskFilter = Builders<AgentTaskDocument>.Filter.Eq(x => x.AgentId, agentId);
|
||||
var agentCodeFilter = Builders<AgentCodeDocument>.Filter.Eq(x => x.AgentId, agentId);
|
||||
var agentCodeFilter = Builders<AgentCodeScriptDocument>.Filter.Eq(x => x.AgentId, agentId);
|
||||
|
||||
_dc.UserAgents.DeleteMany(userAgentFilter);
|
||||
_dc.RoleAgents.DeleteMany(roleAgentFilter);
|
||||
_dc.AgentTasks.DeleteMany(agentTaskFilter);
|
||||
_dc.AgentCodes.DeleteMany(agentCodeFilter);
|
||||
_dc.AgentCodeScripts.DeleteMany(agentCodeFilter);
|
||||
_dc.Agents.DeleteOne(agentFilter);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,113 +0,0 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
|
||||
namespace BotSharp.Plugin.MongoStorage.Repository;
|
||||
|
||||
public partial class MongoRepository
|
||||
{
|
||||
#region Code
|
||||
public List<AgentCodeScript> GetAgentCodeScripts(string agentId, List<string>? scriptNames = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId))
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
var builder = Builders<AgentCodeDocument>.Filter;
|
||||
var filters = new List<FilterDefinition<AgentCodeDocument>>()
|
||||
{
|
||||
builder.Eq(x => x.AgentId, agentId)
|
||||
};
|
||||
|
||||
if (!scriptNames.IsNullOrEmpty())
|
||||
{
|
||||
filters.Add(builder.In(x => x.Name, scriptNames));
|
||||
}
|
||||
|
||||
var found = _dc.AgentCodes.Find(builder.And(filters)).ToList();
|
||||
return found.Select(x => AgentCodeDocument.ToDomainModel(x)).ToList();
|
||||
}
|
||||
|
||||
public string? GetAgentCodeScript(string agentId, string scriptName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId)
|
||||
|| string.IsNullOrWhiteSpace(scriptName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var builder = Builders<AgentCodeDocument>.Filter;
|
||||
var filters = new List<FilterDefinition<AgentCodeDocument>>()
|
||||
{
|
||||
builder.Eq(x => x.AgentId, agentId),
|
||||
builder.Eq(x => x.Name, scriptName)
|
||||
};
|
||||
|
||||
var found = _dc.AgentCodes.Find(builder.And(filters)).FirstOrDefault();
|
||||
return found?.Content;
|
||||
}
|
||||
|
||||
public bool UpdateAgentCodeScripts(string agentId, List<AgentCodeScript> scripts)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId) || scripts.IsNullOrEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var builder = Builders<AgentCodeDocument>.Filter;
|
||||
var ops = scripts.Where(x => !string.IsNullOrWhiteSpace(x.Name))
|
||||
.Select(x => new UpdateOneModel<AgentCodeDocument>(
|
||||
builder.And(new List<FilterDefinition<AgentCodeDocument>>
|
||||
{
|
||||
builder.Eq(y => y.AgentId, agentId),
|
||||
builder.Eq(y => y.Name, x.Name)
|
||||
}),
|
||||
Builders<AgentCodeDocument>.Update.Set(y => y.Content, x.Content)
|
||||
))
|
||||
.ToList();
|
||||
|
||||
var result = _dc.AgentCodes.BulkWrite(ops, new BulkWriteOptions { IsOrdered = false });
|
||||
return result.ModifiedCount > 0 || result.MatchedCount > 0;
|
||||
}
|
||||
|
||||
public bool BulkInsertAgentCodeScripts(string agentId, List<AgentCodeScript> scripts)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId) || scripts.IsNullOrEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var docs = scripts.Select(x =>
|
||||
{
|
||||
var script = AgentCodeDocument.ToMongoModel(x);
|
||||
script.AgentId = agentId;
|
||||
script.Id = !string.IsNullOrEmpty(x.Id) ? x.Id : Guid.NewGuid().ToString();
|
||||
return script;
|
||||
}).ToList();
|
||||
|
||||
_dc.AgentCodes.InsertMany(docs);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DeleteAgentCodeScripts(string agentId, List<string>? scriptNames)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var filterDef = Builders<AgentCodeDocument>.Filter.Empty;
|
||||
if (scriptNames != null)
|
||||
{
|
||||
var builder = Builders<AgentCodeDocument>.Filter;
|
||||
var filters = new List<FilterDefinition<AgentCodeDocument>>
|
||||
{
|
||||
builder.In(x => x.Name, scriptNames)
|
||||
};
|
||||
filterDef = builder.And(filters);
|
||||
}
|
||||
|
||||
var deleted = _dc.AgentCodes.DeleteMany(filterDef);
|
||||
return deleted.DeletedCount > 0;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
|
||||
namespace BotSharp.Plugin.MongoStorage.Repository;
|
||||
|
||||
public partial class MongoRepository
|
||||
{
|
||||
#region Code
|
||||
public List<AgentCodeScript> GetAgentCodeScripts(string agentId, AgentCodeScriptFilter? filter = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId))
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
filter ??= AgentCodeScriptFilter.Empty();
|
||||
|
||||
var builder = Builders<AgentCodeScriptDocument>.Filter;
|
||||
var filters = new List<FilterDefinition<AgentCodeScriptDocument>>()
|
||||
{
|
||||
builder.Eq(x => x.AgentId, agentId)
|
||||
};
|
||||
|
||||
if (!filter.ScriptNames.IsNullOrEmpty())
|
||||
{
|
||||
filters.Add(builder.In(x => x.Name, filter.ScriptNames));
|
||||
}
|
||||
if (!filter.ScriptTypes.IsNullOrEmpty())
|
||||
{
|
||||
filters.Add(builder.In(x => x.ScriptType, filter.ScriptTypes));
|
||||
}
|
||||
|
||||
var found = _dc.AgentCodeScripts.Find(builder.And(filters)).ToList();
|
||||
return found.Select(x => AgentCodeScriptDocument.ToDomainModel(x)).ToList();
|
||||
}
|
||||
|
||||
public string? GetAgentCodeScript(string agentId, string scriptName, string scriptType = AgentCodeScriptType.Src)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId)
|
||||
|| string.IsNullOrWhiteSpace(scriptName)
|
||||
|| string.IsNullOrWhiteSpace(scriptType))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var builder = Builders<AgentCodeScriptDocument>.Filter;
|
||||
var filters = new List<FilterDefinition<AgentCodeScriptDocument>>()
|
||||
{
|
||||
builder.Eq(x => x.AgentId, agentId),
|
||||
builder.Eq(x => x.Name, scriptName),
|
||||
builder.Eq(x => x.ScriptType, scriptType)
|
||||
};
|
||||
|
||||
var found = _dc.AgentCodeScripts.Find(builder.And(filters)).FirstOrDefault();
|
||||
return found?.Content;
|
||||
}
|
||||
|
||||
public bool UpdateAgentCodeScripts(string agentId, List<AgentCodeScript> scripts)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId) || scripts.IsNullOrEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var builder = Builders<AgentCodeScriptDocument>.Filter;
|
||||
var ops = scripts.Where(x => !string.IsNullOrWhiteSpace(x.Name))
|
||||
.Select(x => new UpdateOneModel<AgentCodeScriptDocument>(
|
||||
builder.And(new List<FilterDefinition<AgentCodeScriptDocument>>
|
||||
{
|
||||
builder.Eq(y => y.AgentId, agentId),
|
||||
builder.Eq(y => y.Name, x.Name),
|
||||
builder.Eq(y => y.ScriptType, x.ScriptType)
|
||||
}),
|
||||
Builders<AgentCodeScriptDocument>.Update.Set(y => y.Content, x.Content)
|
||||
))
|
||||
.ToList();
|
||||
|
||||
var result = _dc.AgentCodeScripts.BulkWrite(ops, new BulkWriteOptions { IsOrdered = false });
|
||||
return result.ModifiedCount > 0 || result.MatchedCount > 0;
|
||||
}
|
||||
|
||||
public bool BulkInsertAgentCodeScripts(string agentId, List<AgentCodeScript> scripts)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId) || scripts.IsNullOrEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var docs = scripts.Select(x =>
|
||||
{
|
||||
var script = AgentCodeScriptDocument.ToMongoModel(x);
|
||||
script.AgentId = agentId;
|
||||
script.Id = x.Id.IfNullOrEmptyAs(Guid.NewGuid().ToString());
|
||||
return script;
|
||||
}).ToList();
|
||||
|
||||
_dc.AgentCodeScripts.InsertMany(docs);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DeleteAgentCodeScripts(string agentId, List<AgentCodeScript>? scripts = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(agentId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DeleteResult deleted;
|
||||
if (scripts != null)
|
||||
{
|
||||
var scriptPaths = scripts.Select(x => x.CodePath);
|
||||
var exprFilter = new BsonDocument("$expr", new BsonDocument("$in", new BsonArray
|
||||
{
|
||||
new BsonDocument("$concat", new BsonArray { "$ScriptType", "/", "$Name" }),
|
||||
new BsonArray(scriptPaths)
|
||||
}));
|
||||
|
||||
var filterDef = new BsonDocumentFilterDefinition<AgentCodeScriptDocument>(exprFilter);
|
||||
deleted = _dc.AgentCodeScripts.DeleteMany(filterDef);
|
||||
}
|
||||
else
|
||||
{
|
||||
deleted = _dc.AgentCodeScripts.DeleteMany(Builders<AgentCodeScriptDocument>.Filter.Empty);
|
||||
}
|
||||
|
||||
return deleted.DeletedCount > 0;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
Loading…
Reference in a new issue