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 }