Skip to main content
Glama
orneryd

M.I.M.I.R - Multi-agent Intelligent Memory & Insight Repository

by orneryd
registry.go5.38 kB
// Package registry provides a plugin system for APOC functions. // // This package allows APOC functions to be registered and called dynamically // at runtime, enabling a flexible plugin architecture for extending Cypher // query capabilities. package registry import ( "fmt" "reflect" "sync" ) // FunctionRegistry manages all registered APOC functions. type FunctionRegistry struct { functions map[string]*FunctionDescriptor mu sync.RWMutex } // FunctionDescriptor describes a registered function. type FunctionDescriptor struct { Name string // Full name (e.g., "apoc.coll.sum") Category string // Category (e.g., "coll", "text", "math") Function interface{} // The actual function Description string // Human-readable description Examples []string // Usage examples Handler func(args []interface{}) interface{} // Wrapper for type-safe execution } // Global registry instance var globalRegistry = NewFunctionRegistry() // NewFunctionRegistry creates a new function registry. func NewFunctionRegistry() *FunctionRegistry { return &FunctionRegistry{ functions: make(map[string]*FunctionDescriptor), } } // Register registers a function with the global registry. // // Example: // Register("apoc.coll.sum", "coll", coll.Sum, "Sum numeric values", []string{"apoc.coll.sum([1,2,3]) => 6"}) func Register(name, category string, fn interface{}, description string, examples []string) error { return globalRegistry.RegisterFunction(name, category, fn, description, examples) } // RegisterFunction registers a function in the registry. func (r *FunctionRegistry) RegisterFunction(name, category string, fn interface{}, description string, examples []string) error { r.mu.Lock() defer r.mu.Unlock() if _, exists := r.functions[name]; exists { return fmt.Errorf("function %s already registered", name) } // Create type-safe handler handler, err := createHandler(fn) if err != nil { return fmt.Errorf("failed to create handler for %s: %w", name, err) } r.functions[name] = &FunctionDescriptor{ Name: name, Category: category, Function: fn, Description: description, Examples: examples, Handler: handler, } return nil } // Call calls a registered function by name with the given arguments. // // Example: // result, err := Call("apoc.coll.sum", []interface{}{[]interface{}{1, 2, 3}}) func Call(name string, args []interface{}) (interface{}, error) { return globalRegistry.CallFunction(name, args) } // CallFunction calls a registered function. func (r *FunctionRegistry) CallFunction(name string, args []interface{}) (interface{}, error) { r.mu.RLock() descriptor, exists := r.functions[name] r.mu.RUnlock() if !exists { return nil, fmt.Errorf("function %s not found", name) } // Call the handler result := descriptor.Handler(args) return result, nil } // Get retrieves a function descriptor by name. func (r *FunctionRegistry) Get(name string) (*FunctionDescriptor, bool) { r.mu.RLock() defer r.mu.RUnlock() descriptor, exists := r.functions[name] return descriptor, exists } // List returns all registered function names. func (r *FunctionRegistry) List() []string { r.mu.RLock() defer r.mu.RUnlock() names := make([]string, 0, len(r.functions)) for name := range r.functions { names = append(names, name) } return names } // ListByCategory returns all function names in a category. func (r *FunctionRegistry) ListByCategory(category string) []string { r.mu.RLock() defer r.mu.RUnlock() names := make([]string, 0) for name, descriptor := range r.functions { if descriptor.Category == category { names = append(names, name) } } return names } // Categories returns all registered categories. func (r *FunctionRegistry) Categories() []string { r.mu.RLock() defer r.mu.RUnlock() categories := make(map[string]bool) for _, descriptor := range r.functions { categories[descriptor.Category] = true } result := make([]string, 0, len(categories)) for category := range categories { result = append(result, category) } return result } // Unregister removes a function from the registry. func (r *FunctionRegistry) Unregister(name string) { r.mu.Lock() defer r.mu.Unlock() delete(r.functions, name) } // Clear removes all functions from the registry. func (r *FunctionRegistry) Clear() { r.mu.Lock() defer r.mu.Unlock() r.functions = make(map[string]*FunctionDescriptor) } // createHandler creates a type-safe handler for a function. func createHandler(fn interface{}) (func([]interface{}) interface{}, error) { fnValue := reflect.ValueOf(fn) fnType := fnValue.Type() if fnType.Kind() != reflect.Func { return nil, fmt.Errorf("not a function") } return func(args []interface{}) interface{} { // Convert args to reflect.Value in := make([]reflect.Value, len(args)) for i, arg := range args { in[i] = reflect.ValueOf(arg) } // Call function out := fnValue.Call(in) // Return first result (or nil if no results) if len(out) == 0 { return nil } return out[0].Interface() }, nil } // GetGlobalRegistry returns the global registry instance. func GetGlobalRegistry() *FunctionRegistry { return globalRegistry }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/orneryd/Mimir'

If you have feedback or need assistance with the MCP directory API, please join our Discord server