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
7 changes: 2 additions & 5 deletions src/Infrastructure/BotSharp.Abstraction/Agents/IAgentHook.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
using BotSharp.Abstraction.Functions.Models;
using BotSharp.Abstraction.Hooks;

namespace BotSharp.Abstraction.Agents;

public interface IAgentHook
public interface IAgentHook : IHookBase
{
/// <summary>
/// Agent Id
/// </summary>
string SelfId { get; }
Agent Agent { get; }
void SetAgent(Agent agent);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using BotSharp.Abstraction.Hooks;

namespace BotSharp.Abstraction.Conversations;

public interface IConversationHook
public interface IConversationHook : IHookBase
{
int Priority { get; }
Agent Agent { get; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using BotSharp.Abstraction.Hooks;

namespace BotSharp.Abstraction.Crontab;

public interface ICrontabHook
public interface ICrontabHook : IHookBase
{
string[]? Triggers
=> null;
Expand Down
17 changes: 17 additions & 0 deletions src/Infrastructure/BotSharp.Abstraction/Hooks/IHookBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BotSharp.Abstraction.Hooks
{
public interface IHookBase
{
/// <summary>
/// Agent Id
/// </summary>
string SelfId => string.Empty;
bool IsMatch(string id) => string.IsNullOrEmpty(SelfId) || SelfId == id;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Instructs.Models;

namespace BotSharp.Abstraction.Instructs;

public interface IInstructHook
public interface IInstructHook : IHookBase
{
string SelfId { get; }
Task BeforeCompletion(Agent agent, RoleDialogModel message);
Task AfterCompletion(Agent agent, InstructResult result);
Task OnResponseGenerated(InstructResponseModel response);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using BotSharp.Abstraction.Functions.Models;
using BotSharp.Abstraction.Hooks;

namespace BotSharp.Abstraction.Loggers;

/// <summary>
/// Model content generating hook, it can be used for logging, metrics and tracing.
/// </summary>
public interface IContentGeneratingHook
public interface IContentGeneratingHook : IHookBase
{
/// <summary>
/// Before content generating.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using BotSharp.Abstraction.Hooks;

namespace BotSharp.Abstraction.Planning;

public interface IPlanningHook
public interface IPlanningHook : IHookBase
{
Task<string> GetSummaryAdditionalRequirements(string planner, RoleDialogModel message)
=> Task.FromResult(string.Empty);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.MLTasks;

namespace BotSharp.Abstraction.Realtime;

public interface IRealtimeHook
public interface IRealtimeHook : IHookBase
{
Task OnModelReady(Agent agent, IRealTimeCompletion completer);
string[] OnModelTranscriptPrompt(Agent agent);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using BotSharp.Abstraction.Functions.Models;
using BotSharp.Abstraction.Hooks;

namespace BotSharp.Abstraction.Routing;

public interface IRoutingHook
public interface IRoutingHook : IHookBase
{
/// <summary>
/// Routing instruction is received from Router
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,6 @@ await HookEmitter.Emit<ICrontabHook>(_services, async hook =>
await hook.OnCronTriggered(item);
await hook.OnTaskExecuted(item);
}
});
}, item.AgentId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ await _completer.Connect(
// Not TriggerModelInference, waiting for user utter.
var instruction = await _completer.UpdateSession(_conn, isInit: true);
var data = _conn.OnModelReady();
await HookEmitter.Emit<IRealtimeHook>(_services, async hook => await hook.OnModelReady(agent, _completer));
await HookEmitter.Emit<IRealtimeHook>(_services, async hook => await hook.OnModelReady(agent, _completer),
agent.Id);
await (init?.Invoke(data) ?? Task.CompletedTask);
},
onModelAudioDeltaReceived: async (audioDeltaData, itemId) =>
Expand Down Expand Up @@ -92,7 +93,8 @@ await _completer.Connect(
if (message.FunctionName == "route_to_agent")
{
var instruction = JsonSerializer.Deserialize<FunctionCallFromLlm>(message.FunctionArgs, BotSharpOptions.defaultJsonOptions);
await HookEmitter.Emit<IRoutingHook>(_services, async hook => await hook.OnRoutingInstructionReceived(instruction, message));
await HookEmitter.Emit<IRoutingHook>(_services, async hook => await hook.OnRoutingInstructionReceived(instruction, message),
agent.Id);
}

await routing.InvokeFunction(message.FunctionName, message);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using BotSharp.Abstraction.Infrastructures;
using BotSharp.Abstraction.Routing.Models;
using System.Collections.Concurrent;

Expand All @@ -10,29 +11,12 @@ public partial class AgentService
// [SharpCache(10, perInstanceCache: true)]
public async Task<Agent> 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;

var hooks = _services.GetServices<IAgentHook>();

// Before agent is loaded.
foreach (var hook in hooks)
{
if (!string.IsNullOrEmpty(hook.SelfId) && hook.SelfId != id)
{
continue;
}

hook.OnAgentLoading(ref id);
}
HookEmitter.Emit<IAgentHook>(_services, hook => hook.OnAgentLoading(ref id), id);

var agent = await GetAgent(id);
if (agent == null)
{
return null;
}
if (agent == null) return null;

await InheritAgent(agent);
OverrideInstructionByChannel(agent);
Expand All @@ -43,13 +27,7 @@ public async Task<Agent> LoadAgent(string id, bool loadUtility = true)
PopulateState(agent.TemplateDict);

// After agent is loaded
foreach (var hook in hooks)
{
if (!string.IsNullOrEmpty(hook.SelfId) && hook.SelfId != id)
{
continue;
}

HookEmitter.Emit<IAgentHook>(_services, hook => {
hook.SetAgent(agent);

if (!string.IsNullOrEmpty(agent.Instruction))
Expand All @@ -72,13 +50,14 @@ public async Task<Agent> LoadAgent(string id, bool loadUtility = true)
hook.OnAgentUtilityLoaded(agent);
}

if(!agent.McpTools.IsNullOrEmpty())
if (!agent.McpTools.IsNullOrEmpty())
{
hook.OnAgentMcpToolLoaded(agent);
}

hook.OnAgentLoaded(agent);
}

}, id);

_logger.LogInformation($"Loaded agent {agent}.");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,8 @@ public string RenderedTemplate(Agent agent, string templateName)
agent.TemplateDict[TemplateRenderConstant.RENDER_AGENT] = agent;
var content = render.Render(template, agent.TemplateDict);

HookEmitter.Emit<IContentGeneratingHook>(_services, async hook =>
await hook.OnRenderingTemplate(agent, templateName, content)
).Wait();
HookEmitter.Emit<IContentGeneratingHook>(_services, async hook => await hook.OnRenderingTemplate(agent, templateName, content),
agent.Id).Wait();

return content;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,14 @@ response.RichContent is RichContent<IRichMessage> template &&
// Emit conversation ending hook
if (response.Instruction.ConversationEnd)
{
await HookEmitter.Emit<IConversationHook>(_services, async hook =>
await hook.OnConversationEnding(response)
);
await HookEmitter.Emit<IConversationHook>(_services, async hook => await hook.OnConversationEnding(response),
response.CurrentAgentId);
response.FunctionName = "conversation_end";
}
}

await HookEmitter.Emit<IConversationHook>(_services, async hook =>
await hook.OnResponseGenerated(response)
);
await HookEmitter.Emit<IConversationHook>(_services, async hook => await hook.OnResponseGenerated(response),
response.CurrentAgentId);

await onResponseReceived(response);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using BotSharp.Abstraction.Instructs.Models;
using BotSharp.Abstraction.Instructs;
using System.IO;
using BotSharp.Abstraction.Infrastructures;

namespace BotSharp.Core.Files.Services;

Expand All @@ -24,14 +25,7 @@ public async Task<string> ReadImages(string text, IEnumerable<InstructFileModel>
}
});

var hooks = _services.GetServices<IInstructHook>();
foreach (var hook in hooks)
{
if (!string.IsNullOrEmpty(hook.SelfId) && hook.SelfId != innerAgentId)
{
continue;
}

await HookEmitter.Emit<IInstructHook>(_services, async hook =>
await hook.OnResponseGenerated(new InstructResponseModel
{
AgentId = innerAgentId,
Expand All @@ -41,8 +35,7 @@ await hook.OnResponseGenerated(new InstructResponseModel
UserMessage = text,
SystemInstruction = instruction,
CompletionText = message.Content
});
}
}), innerAgentId);

return message.Content;
}
Expand All @@ -59,14 +52,7 @@ public async Task<RoleDialogModel> GenerateImage(string text, InstructOptions? o
Instruction = instruction
}, new RoleDialogModel(AgentRole.User, instruction ?? text));

var hooks = _services.GetServices<IInstructHook>();
foreach (var hook in hooks)
{
if (!string.IsNullOrEmpty(hook.SelfId) && hook.SelfId != innerAgentId)
{
continue;
}

await HookEmitter.Emit<IInstructHook>(_services, async hook =>
await hook.OnResponseGenerated(new InstructResponseModel
{
AgentId = innerAgentId,
Expand All @@ -76,8 +62,7 @@ await hook.OnResponseGenerated(new InstructResponseModel
UserMessage = text,
SystemInstruction = instruction,
CompletionText = message.Content
});
}
}), innerAgentId);

return message;
}
Expand All @@ -104,23 +89,15 @@ public async Task<RoleDialogModel> VaryImage(InstructFileModel image, InstructOp

stream.Close();

var hooks = _services.GetServices<IInstructHook>();
foreach (var hook in hooks)
{
if (!string.IsNullOrEmpty(hook.SelfId) && hook.SelfId != innerAgentId)
{
continue;
}

await HookEmitter.Emit<IInstructHook>(_services, async hook =>
await hook.OnResponseGenerated(new InstructResponseModel
{
AgentId = innerAgentId,
Provider = completion.Provider,
Model = completion.Model,
UserMessage = string.Empty,
CompletionText = message.Content
});
}
}), innerAgentId);

return message;
}
Expand Down Expand Up @@ -149,14 +126,7 @@ public async Task<RoleDialogModel> EditImage(string text, InstructFileModel imag

stream.Close();

var hooks = _services.GetServices<IInstructHook>();
foreach (var hook in hooks)
{
if (!string.IsNullOrEmpty(hook.SelfId) && hook.SelfId != innerAgentId)
{
continue;
}

await HookEmitter.Emit<IInstructHook>(_services, async hook =>
await hook.OnResponseGenerated(new InstructResponseModel
{
AgentId = innerAgentId,
Expand All @@ -166,8 +136,7 @@ await hook.OnResponseGenerated(new InstructResponseModel
UserMessage = text,
SystemInstruction = instruction,
CompletionText = message.Content
});
}
}), innerAgentId);

return message;
}
Expand Down Expand Up @@ -205,14 +174,7 @@ public async Task<RoleDialogModel> EditImage(string text, InstructFileModel imag
imageStream.Close();
maskStream.Close();

var hooks = _services.GetServices<IInstructHook>();
foreach (var hook in hooks)
{
if (!string.IsNullOrEmpty(hook.SelfId) && hook.SelfId != innerAgentId)
{
continue;
}

await HookEmitter.Emit<IInstructHook>(_services, async hook =>
await hook.OnResponseGenerated(new InstructResponseModel
{
AgentId = innerAgentId,
Expand All @@ -222,8 +184,7 @@ await hook.OnResponseGenerated(new InstructResponseModel
UserMessage = text,
SystemInstruction = instruction,
CompletionText = message.Content
});
}
}), innerAgentId);

return message;
}
Expand Down
Loading
Loading