Skip to content
Open
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
10 changes: 7 additions & 3 deletions transports/bifrost-http/lib/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5131,13 +5131,17 @@ func (c *Config) rebuildInterfaceCaches() {
var httpTransport []schemas.HTTPTransportPlugin

for _, p := range *basePlugins {
if llmPlugin, ok := p.(schemas.LLMPlugin); ok {
// Use the framework's As* helpers rather than bare type assertions: a .so plugin
// is wrapped in a DynamicPlugin that satisfies every hook interface even when the
// .so exports none of those symbols, so bare assertions put every dynamic plugin
// into all three caches and invoke no-op hooks on every request.
if llmPlugin := plugins.AsLLMPlugin(p); llmPlugin != nil {
llm = append(llm, llmPlugin)
}
if mcpPlugin, ok := p.(schemas.MCPPlugin); ok {
if mcpPlugin := plugins.AsMCPPlugin(p); mcpPlugin != nil {
mcp = append(mcp, mcpPlugin)
}
if httpPlugin, ok := p.(schemas.HTTPTransportPlugin); ok {
if httpPlugin := plugins.AsHTTPTransportPlugin(p); httpPlugin != nil {
httpTransport = append(httpTransport, httpPlugin)
}
if cm, ok := p.(schemas.ConfigMarshallerPlugin); ok {
Expand Down
15 changes: 11 additions & 4 deletions transports/bifrost-http/server/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"slices"

"github.com/maximhq/bifrost/core/schemas"
dynamicPlugins "github.com/maximhq/bifrost/framework/plugins"
"github.com/maximhq/bifrost/plugins/compat"
"github.com/maximhq/bifrost/plugins/governance"
"github.com/maximhq/bifrost/plugins/logging"
Expand All @@ -20,16 +21,22 @@ import (
"github.com/maximhq/bifrost/transports/bifrost-http/lib"
)

// InferPluginTypes determines which interface types a plugin implements
// InferPluginTypes determines which interface types a plugin implements.
// A .so plugin is wrapped in a DynamicPlugin, which structurally satisfies every hook
// interface regardless of which symbols the .so actually exports, so a plain type
// assertion reports all three types for every dynamic plugin. That made RemovePlugin
// remove the same instance from both the LLM and MCP lists and call Cleanup() once per
// list. The framework's As* helpers additionally check the hook function pointers, so
// dynamic plugins are classified by the symbols they really export.
func InferPluginTypes(plugin schemas.BasePlugin) []schemas.PluginType {
var types []schemas.PluginType
if _, ok := plugin.(schemas.LLMPlugin); ok {
if dynamicPlugins.AsLLMPlugin(plugin) != nil {
types = append(types, schemas.PluginTypeLLM)
}
if _, ok := plugin.(schemas.MCPPlugin); ok {
if dynamicPlugins.AsMCPPlugin(plugin) != nil {
types = append(types, schemas.PluginTypeMCP)
}
if _, ok := plugin.(schemas.HTTPTransportPlugin); ok {
if dynamicPlugins.AsHTTPTransportPlugin(plugin) != nil {
types = append(types, schemas.PluginTypeHTTP)
}
return types
Expand Down