Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public interface IAgentService

FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def);

bool RenderVisibility(string? visibilityExpression, Dictionary<string, object> dict);

/// <summary>
/// Get agent detail without trigger any hook.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,38 @@ namespace BotSharp.Abstraction.Agents.Models;

public class AgentUtility
{
public string Category { get; set; }
public string Name { get; set; }
public bool Disabled { get; set; }
public IEnumerable<UtilityFunction> Functions { get; set; } = [];
public IEnumerable<UtilityTemplate> Templates { get; set; } = [];

public AgentUtility()
{

}

public AgentUtility(
string name,
IEnumerable<UtilityFunction>? functions = null,
IEnumerable<UtilityTemplate>? templates = null)
{
Name = name;
Functions = functions ?? [];
Templates = templates ?? [];
}

public override string ToString()
{
return Name;
}
}
[JsonPropertyName("visibility_expression")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? VisibilityExpression { get; set; }

public IEnumerable<UtilityItem> Items { get; set; } = [];

public class UtilityFunction : UtilityBase
{
public UtilityFunction()
public AgentUtility()
{

}

public UtilityFunction(string name)
public override string ToString()
{
Name = name;
return $"{Category}-{Name}";
}
}

public class UtilityTemplate : UtilityBase
public class UtilityItem
{
public UtilityTemplate()
{

}
[JsonPropertyName("function_name")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? FunctionName { get; set; }

public UtilityTemplate(string name)
{
Name = name;
}
}
[JsonPropertyName("template_name")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? TemplateName { get; set; }

public class UtilityBase
{
public string Name { get; set; }
[JsonPropertyName("visibility_expression")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? VisibilityExpression { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ namespace BotSharp.Core.Crontab.Enum;

public class UtilityName
{
public const string ScheduleTask = "crontab.schedule-task";
public const string ScheduleTask = "schedule-task";
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,19 @@ public void AddUtilities(List<AgentUtility> utilities)
{
new AgentUtility
{
Category = "crontab",
Name = UtilityName.ScheduleTask,
Functions = [new(SCHEDULE_TASK_FN), new(TASK_WAIT_FN)],
Templates = [new($"{SCHEDULE_TASK_FN}.fn")]
Items = [
new UtilityItem
{
FunctionName = SCHEDULE_TASK_FN,
TemplateName = $"{SCHEDULE_TASK_FN}.fn"
},
new UtilityItem
{
FunctionName = TASK_WAIT_FN
},
]
}
};

Expand Down
48 changes: 33 additions & 15 deletions src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public override void OnAgentUtilityLoaded(Agent agent)
var isConvMode = conv.IsConversationMode();
if (!isConvMode) return;

agent.Utilities ??= [];
agent.SecondaryFunctions ??= [];
agent.SecondaryInstructions ??= [];
agent.Utilities ??= [];

var (functions, templates) = GetUtilityContent(agent);

Expand All @@ -34,7 +34,7 @@ public override void OnAgentUtilityLoaded(Agent agent)
private (IEnumerable<FunctionDef>, IEnumerable<AgentTemplate>) GetUtilityContent(Agent agent)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
var (functionNames, templateNames) = GetUniqueContent(agent.Utilities);
var (functionNames, templateNames) = FilterUtilityContent(agent.Utilities, agent);

if (agent.MergeUtility)
{
Expand All @@ -43,7 +43,7 @@ public override void OnAgentUtilityLoaded(Agent agent)
if (!string.IsNullOrEmpty(entryAgentId))
{
var entryAgent = db.GetAgent(entryAgentId, basicsOnly: true);
var (fns, tps) = GetUniqueContent(entryAgent?.Utilities);
var (fns, tps) = FilterUtilityContent(entryAgent?.Utilities, agent);
functionNames = functionNames.Concat(fns).Distinct().ToList();
templateNames = templateNames.Concat(tps).Distinct().ToList();
}
Expand All @@ -55,23 +55,41 @@ public override void OnAgentUtilityLoaded(Agent agent)
return (functions, templates);
}

private (IEnumerable<string>, IEnumerable<string>) GetUniqueContent(IEnumerable<AgentUtility>? utilities)
private (IEnumerable<string>, IEnumerable<string>) FilterUtilityContent(IEnumerable<AgentUtility>? utilities, Agent agent)
{
if (utilities.IsNullOrEmpty())
{
return ([], []);
}

utilities = utilities?.Where(x => !string.IsNullOrEmpty(x.Name) && !x.Disabled)?.ToList() ?? [];
var functionNames = utilities.SelectMany(x => x.Functions)
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX))
.Select(x => x.Name)
.Distinct().ToList();
var templateNames = utilities.SelectMany(x => x.Templates)
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX))
.Select(x => x.Name)
.Distinct().ToList();

return (functionNames, templateNames);
var agentService = _services.GetRequiredService<IAgentService>();
var innerUtilities = utilities!.Where(x => !string.IsNullOrEmpty(x.Name) && !x.Disabled).ToList();

var functionNames = new List<string>();
var templateNames = new List<string>();

foreach (var utility in innerUtilities)
{
var isVisible = agentService.RenderVisibility(utility.VisibilityExpression, agent.TemplateDict);
if (!isVisible || utility.Items.IsNullOrEmpty()) continue;

foreach (var item in utility.Items)
{
isVisible = agentService.RenderVisibility(item.VisibilityExpression, agent.TemplateDict);
if (!isVisible) continue;

if (item.FunctionName?.StartsWith(UTIL_PREFIX) == true)
{
functionNames.Add(item.FunctionName);
}

if (item.TemplateName?.StartsWith(UTIL_PREFIX) == true)
{
templateNames.Add(item.TemplateName);
}
}
}

return (functionNames.Distinct(), templateNames.Distinct());
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using BotSharp.Abstraction.Infrastructures;
using BotSharp.Abstraction.Routing.Models;
using System.Collections.Concurrent;

Expand All @@ -18,12 +17,15 @@ public async Task<Agent> LoadAgent(string id, bool loadUtility = true)
var agent = await GetAgent(id);
if (agent == null) return null;

agent.TemplateDict = [];
agent.SecondaryInstructions = [];
agent.SecondaryFunctions = [];

await InheritAgent(agent);
OverrideInstructionByChannel(agent);
AddOrUpdateParameters(agent);

// Populate state into dictionary
agent.TemplateDict = new Dictionary<string, object>();
PopulateState(agent.TemplateDict);

// After agent is loaded
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,7 @@ public bool RenderFunction(Agent agent, FunctionDef def)

if (!string.IsNullOrWhiteSpace(def.VisibilityExpression))
{
var render = _services.GetRequiredService<ITemplateRender>();
var result = render.Render(def.VisibilityExpression, new Dictionary<string, object>
{
{ "states", agent.TemplateDict }
});
isRender = isRender && result == "visible";
isRender = RenderVisibility(def.VisibilityExpression, agent.TemplateDict);
}

return isRender;
Expand All @@ -76,12 +71,7 @@ public bool RenderFunction(Agent agent, FunctionDef def)
if (node.TryGetProperty(visibleExpress, out var element))
{
var expression = element.GetString();
var render = _services.GetRequiredService<ITemplateRender>();
var result = render.Render(expression, new Dictionary<string, object>
{
{ "states", agent.TemplateDict }
});
matched = result == "visible";
matched = RenderVisibility(expression, agent.TemplateDict);
}

if (matched)
Expand Down Expand Up @@ -137,4 +127,20 @@ public string RenderedTemplate(Agent agent, string templateName)

return content;
}

public bool RenderVisibility(string? visibilityExpression, Dictionary<string, object> dict)
{
if (string.IsNullOrWhiteSpace(visibilityExpression))
{
return true;
}

var render = _services.GetRequiredService<ITemplateRender>();
var result = render.Render(visibilityExpression, new Dictionary<string, object>
{
{ "states", dict ?? [] }
});

return result.IsEqualTo("visible");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ public void AddUtilities(List<AgentUtility> utilities)
{
utilities.Add(new AgentUtility
{
Name = "instruct.template",
Functions = [new($"{EXECUTE_TEMPLATE}")],
Templates = [new($"{EXECUTE_TEMPLATE}.fn")]
Category = "instruct",
Name = "template",
Items = [
new UtilityItem {
FunctionName = $"{EXECUTE_TEMPLATE}",
TemplateName = $"{EXECUTE_TEMPLATE}.fn"
}
]
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,20 @@ public void AddUtilities(List<AgentUtility> utilities)
{
utilities.Add(new AgentUtility
{
Category = "routing",
Name = "routing.tools",
Functions = [new($"{REDIRECT_TO_AGENT}"), new($"{FALLBACK_TO_ROUTER}")],
Templates = [new($"{REDIRECT_TO_AGENT}.fn"), new($"{FALLBACK_TO_ROUTER}.fn")]
Items = [
new UtilityItem
{
FunctionName = $"{REDIRECT_TO_AGENT}",
TemplateName = $"{REDIRECT_TO_AGENT}.fn"
},
new UtilityItem
{
FunctionName = $"{FALLBACK_TO_ROUTER}",
TemplateName = $"{FALLBACK_TO_ROUTER}.fn"
}
]
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,9 @@ public IEnumerable<AgentUtility> GetAgentUtilityOptions()
{
hook.AddUtilities(utilities);
}
return utilities.Where(x => !string.IsNullOrWhiteSpace(x.Name)).OrderBy(x => x.Name).ToList();
return utilities.Where(x => !string.IsNullOrWhiteSpace(x.Category)
&& !string.IsNullOrWhiteSpace(x.Name)
&& !x.Items.IsNullOrEmpty()).ToList();
}

[HttpGet("/agent/labels")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ namespace BotSharp.Plugin.AudioHandler.Enums;

public class UtilityName
{
public const string AudioHandler = "audio.audio-handler";
public const string AudioHandler = "audio-handler";
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@ public void AddUtilities(List<AgentUtility> utilities)
{
var utility = new AgentUtility
{
Category = "audio",
Name = UtilityName.AudioHandler,
Functions = [new(HANDLER_AUDIO)],
Templates = [new($"{HANDLER_AUDIO}.fn")]
Items = [
new UtilityItem
{
FunctionName = HANDLER_AUDIO,
TemplateName = $"{HANDLER_AUDIO}.fn"
}
]
};

utilities.Add(utility);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ namespace BotSharp.Plugin.EmailHandler.Enums;

public class UtilityName
{
public const string EmailHandler = "email.email-handler";
public const string EmailHandler = "email-handler";
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,20 @@ public void AddUtilities(List<AgentUtility> utilities)
{
var utility = new AgentUtility
{
Category = "email",
Name = UtilityName.EmailHandler,
Functions = [new(EMAIL_READER_FN), new(EMAIL_SENDER_FN)],
Templates = [new($"{EMAIL_READER_FN}.fn"), new($"{EMAIL_SENDER_FN}.fn")]
Items = [
new UtilityItem
{
FunctionName = EMAIL_READER_FN,
TemplateName = $"{EMAIL_READER_FN}.fn"
},
new UtilityItem
{
FunctionName = EMAIL_SENDER_FN,
TemplateName = $"{EMAIL_SENDER_FN}.fn"
}
]
};

utilities.Add(utility);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ namespace BotSharp.Plugin.ExcelHandler.Enums;

public class UtilityName
{
public const string ExcelHandler = "excel.excel-handler";
public const string ExcelHandler = "excel-handler";
}
Loading
Loading