first commit
This commit is contained in:
162
framework/plugins/main.go
Normal file
162
framework/plugins/main.go
Normal file
@@ -0,0 +1,162 @@
|
||||
// Package plugins provides a framework for dynamically loading and managing plugins
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"github.com/maximhq/bifrost/core/schemas"
|
||||
)
|
||||
|
||||
// PluginConfig is the generic configuration for any plugin type
|
||||
// Plugin types are automatically detected based on implemented interfaces
|
||||
type PluginConfig struct {
|
||||
Path string `json:"path"`
|
||||
Name string `json:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Config any `json:"config,omitempty"`
|
||||
}
|
||||
|
||||
// Config is the configuration for the plugins framework
|
||||
type Config struct {
|
||||
// Plugins is the unified configuration for all plugin types
|
||||
Plugins []PluginConfig `json:"plugins"`
|
||||
}
|
||||
|
||||
// AsLLMPlugin checks if a base plugin implements LLMPlugin and actually has LLM hooks.
|
||||
// For DynamicPlugin, it checks if the hook function pointers are not nil.
|
||||
// Returns nil if the plugin does not implement the interface or has no LLM hooks.
|
||||
func AsLLMPlugin(plugin schemas.BasePlugin) schemas.LLMPlugin {
|
||||
// Check if it's a DynamicPlugin first
|
||||
if dp, ok := plugin.(*DynamicPlugin); ok {
|
||||
// Only return as LLMPlugin if it actually has LLM hooks
|
||||
if dp.preLLMHook != nil || dp.postLLMHook != nil {
|
||||
return dp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// For non-DynamicPlugin types, use normal type assertion
|
||||
if llmPlugin, ok := plugin.(schemas.LLMPlugin); ok {
|
||||
return llmPlugin
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AsMCPPlugin checks if a base plugin implements MCPPlugin and actually has MCP hooks.
|
||||
// For DynamicPlugin, it checks if the hook function pointers are not nil.
|
||||
// Returns nil if the plugin does not implement the interface or has no MCP hooks.
|
||||
func AsMCPPlugin(plugin schemas.BasePlugin) schemas.MCPPlugin {
|
||||
// Check if it's a DynamicPlugin first
|
||||
if dp, ok := plugin.(*DynamicPlugin); ok {
|
||||
// Only return as MCPPlugin if it actually has MCP hooks
|
||||
if dp.preMCPHook != nil || dp.postMCPHook != nil {
|
||||
return dp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// For non-DynamicPlugin types, use normal type assertion
|
||||
if mcpPlugin, ok := plugin.(schemas.MCPPlugin); ok {
|
||||
return mcpPlugin
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AsHTTPTransportPlugin checks if a base plugin implements HTTPTransportPlugin and actually has HTTP transport hooks.
|
||||
// For DynamicPlugin, it checks if the hook function pointers are not nil.
|
||||
// Returns nil if the plugin does not implement the interface or has no HTTP transport hooks.
|
||||
func AsHTTPTransportPlugin(plugin schemas.BasePlugin) schemas.HTTPTransportPlugin {
|
||||
// Check if it's a DynamicPlugin first
|
||||
if dp, ok := plugin.(*DynamicPlugin); ok {
|
||||
// Only return as HTTPTransportPlugin if it actually has HTTP transport hooks
|
||||
if dp.httpTransportPreHook != nil || dp.httpTransportPostHook != nil {
|
||||
return dp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// For non-DynamicPlugin types, use normal type assertion
|
||||
if httpPlugin, ok := plugin.(schemas.HTTPTransportPlugin); ok {
|
||||
return httpPlugin
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AsObservabilityPlugin checks if a base plugin implements ObservabilityPlugin and actually has observability hooks.
|
||||
// For DynamicPlugin, it checks if the hook function pointer is not nil.
|
||||
// Returns nil if the plugin does not implement the interface or has no observability hooks.
|
||||
func AsObservabilityPlugin(plugin schemas.BasePlugin) schemas.ObservabilityPlugin {
|
||||
// Check if it's a DynamicPlugin first
|
||||
if dp, ok := plugin.(*DynamicPlugin); ok {
|
||||
// Only return as ObservabilityPlugin if it actually has the Inject hook
|
||||
if dp.inject != nil {
|
||||
return dp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// For non-DynamicPlugin types, use normal type assertion
|
||||
if obsPlugin, ok := plugin.(schemas.ObservabilityPlugin); ok {
|
||||
return obsPlugin
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadPlugins loads all plugins from the config
|
||||
func LoadPlugins(loader PluginLoader, config *Config) ([]schemas.BasePlugin, error) {
|
||||
plugins := []schemas.BasePlugin{}
|
||||
if config == nil {
|
||||
return plugins, nil
|
||||
}
|
||||
|
||||
for _, pc := range config.Plugins {
|
||||
if !pc.Enabled {
|
||||
continue
|
||||
}
|
||||
plugin, err := loader.LoadPlugin(pc.Path, pc.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
plugins = append(plugins, plugin)
|
||||
}
|
||||
|
||||
return plugins, nil
|
||||
}
|
||||
|
||||
// FilterLLMPlugins filters a list of BasePlugins to only include those implementing LLMPlugin
|
||||
func FilterLLMPlugins(plugins []schemas.BasePlugin) []schemas.LLMPlugin {
|
||||
result := []schemas.LLMPlugin{}
|
||||
for _, p := range plugins {
|
||||
if llmPlugin := AsLLMPlugin(p); llmPlugin != nil {
|
||||
result = append(result, llmPlugin)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// FilterMCPPlugins filters a list of BasePlugins to only include those implementing MCPPlugin
|
||||
func FilterMCPPlugins(plugins []schemas.BasePlugin) []schemas.MCPPlugin {
|
||||
result := []schemas.MCPPlugin{}
|
||||
for _, p := range plugins {
|
||||
if mcpPlugin := AsMCPPlugin(p); mcpPlugin != nil {
|
||||
result = append(result, mcpPlugin)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// FilterHTTPTransportPlugins filters a list of BasePlugins to only include those implementing HTTPTransportPlugin
|
||||
func FilterHTTPTransportPlugins(plugins []schemas.BasePlugin) []schemas.HTTPTransportPlugin {
|
||||
result := []schemas.HTTPTransportPlugin{}
|
||||
for _, p := range plugins {
|
||||
if httpPlugin := AsHTTPTransportPlugin(p); httpPlugin != nil {
|
||||
result = append(result, httpPlugin)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// FilterObservabilityPlugins filters a list of BasePlugins to only include those implementing ObservabilityPlugin
|
||||
func FilterObservabilityPlugins(plugins []schemas.BasePlugin) []schemas.ObservabilityPlugin {
|
||||
result := []schemas.ObservabilityPlugin{}
|
||||
for _, p := range plugins {
|
||||
if obsPlugin := AsObservabilityPlugin(p); obsPlugin != nil {
|
||||
result = append(result, obsPlugin)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user