/ go / internal / plugins / interface.go
interface.go
  1  package plugins
  2  
  3  import (
  4  	"fmt"
  5  	"plugin"
  6  	"sync"
  7  
  8  	"github.com/TransformerOS/kamaji-go/internal/tools"
  9  	"github.com/TransformerOS/kamaji-go/internal/types"
 10  )
 11  
 12  type Plugin interface {
 13  	Name() string
 14  	Version() string
 15  	Load() error
 16  	Unload() error
 17  	GetTools() []tools.Tool
 18  	GetProviders() []types.LLMProvider
 19  }
 20  
 21  type PluginManager struct {
 22  	plugins map[string]Plugin
 23  	loaded  map[string]*plugin.Plugin
 24  	mutex   sync.RWMutex
 25  }
 26  
 27  func NewPluginManager() *PluginManager {
 28  	return &PluginManager{
 29  		plugins: make(map[string]Plugin),
 30  		loaded:  make(map[string]*plugin.Plugin),
 31  	}
 32  }
 33  
 34  func (pm *PluginManager) LoadPlugin(path string) error {
 35  	pm.mutex.Lock()
 36  	defer pm.mutex.Unlock()
 37  
 38  	// Load the plugin
 39  	p, err := plugin.Open(path)
 40  	if err != nil {
 41  		return fmt.Errorf("failed to open plugin %s: %w", path, err)
 42  	}
 43  
 44  	// Look for the required symbol
 45  	sym, err := p.Lookup("NewPlugin")
 46  	if err != nil {
 47  		return fmt.Errorf("plugin %s missing NewPlugin function: %w", path, err)
 48  	}
 49  
 50  	// Cast to plugin constructor
 51  	newPlugin, ok := sym.(func() Plugin)
 52  	if !ok {
 53  		return fmt.Errorf("plugin %s NewPlugin has wrong signature", path)
 54  	}
 55  
 56  	// Create plugin instance
 57  	pluginInstance := newPlugin()
 58  	
 59  	// Load the plugin
 60  	if err := pluginInstance.Load(); err != nil {
 61  		return fmt.Errorf("failed to load plugin %s: %w", pluginInstance.Name(), err)
 62  	}
 63  
 64  	// Register plugin
 65  	pm.plugins[pluginInstance.Name()] = pluginInstance
 66  	pm.loaded[pluginInstance.Name()] = p
 67  
 68  	// Register tools and providers
 69  	pm.registerPluginComponents(pluginInstance)
 70  
 71  	return nil
 72  }
 73  
 74  func (pm *PluginManager) UnloadPlugin(name string) error {
 75  	pm.mutex.Lock()
 76  	defer pm.mutex.Unlock()
 77  
 78  	pluginInstance, exists := pm.plugins[name]
 79  	if !exists {
 80  		return fmt.Errorf("plugin %s not found", name)
 81  	}
 82  
 83  	// Unload plugin
 84  	if err := pluginInstance.Unload(); err != nil {
 85  		return fmt.Errorf("failed to unload plugin %s: %w", name, err)
 86  	}
 87  
 88  	// Unregister components
 89  	pm.unregisterPluginComponents(pluginInstance)
 90  
 91  	// Remove from registry
 92  	delete(pm.plugins, name)
 93  	delete(pm.loaded, name)
 94  
 95  	return nil
 96  }
 97  
 98  func (pm *PluginManager) registerPluginComponents(p Plugin) {
 99  	// Register tools
100  	for _, tool := range p.GetTools() {
101  		tools.Register(tool)
102  	}
103  
104  	// Register providers would go here when provider registry exists
105  	// for _, provider := range p.GetProviders() {
106  	//     providers.Register(provider)
107  	// }
108  }
109  
110  func (pm *PluginManager) unregisterPluginComponents(p Plugin) {
111  	// Unregister tools (would need unregister function in tools package)
112  	// Unregister providers (would need unregister function in providers package)
113  }
114  
115  func (pm *PluginManager) ListPlugins() []string {
116  	pm.mutex.RLock()
117  	defer pm.mutex.RUnlock()
118  
119  	var names []string
120  	for name := range pm.plugins {
121  		names = append(names, name)
122  	}
123  	return names
124  }
125  
126  func (pm *PluginManager) GetPlugin(name string) (Plugin, bool) {
127  	pm.mutex.RLock()
128  	defer pm.mutex.RUnlock()
129  
130  	plugin, exists := pm.plugins[name]
131  	return plugin, exists
132  }
133  
134  // BasePlugin provides common plugin functionality
135  type BasePlugin struct {
136  	name      string
137  	version   string
138  	tools     []tools.Tool
139  	providers []types.LLMProvider
140  }
141  
142  func NewBasePlugin(name, version string) *BasePlugin {
143  	return &BasePlugin{
144  		name:      name,
145  		version:   version,
146  		tools:     []tools.Tool{},
147  		providers: []types.LLMProvider{},
148  	}
149  }
150  
151  func (bp *BasePlugin) Name() string {
152  	return bp.name
153  }
154  
155  func (bp *BasePlugin) Version() string {
156  	return bp.version
157  }
158  
159  func (bp *BasePlugin) Load() error {
160  	return nil
161  }
162  
163  func (bp *BasePlugin) Unload() error {
164  	return nil
165  }
166  
167  func (bp *BasePlugin) GetTools() []tools.Tool {
168  	return bp.tools
169  }
170  
171  func (bp *BasePlugin) GetProviders() []types.LLMProvider {
172  	return bp.providers
173  }
174  
175  func (bp *BasePlugin) AddTool(tool tools.Tool) {
176  	bp.tools = append(bp.tools, tool)
177  }
178  
179  func (bp *BasePlugin) AddProvider(provider types.LLMProvider) {
180  	bp.providers = append(bp.providers, provider)
181  }