package functions import ( "fmt" "reflect" "strings" "sync" "reichard.io/poiesis/internal/tsconvert" ) var ( functionRegistry = make(map[string]Function) registryMutex sync.RWMutex ) func registerFunction[A Args, R any](name string, isAsync bool, fn GoFunc[A, R]) { // Lock Registry registryMutex.Lock() defer registryMutex.Unlock() // Validate Args Type tType := reflect.TypeFor[A]() if tType.Kind() != reflect.Struct { panic(fmt.Sprintf("function %s: argument must be a struct type, got %v", name, tType)) } // Collect Types and Generate Definition fnType := reflect.TypeOf(fn) types := tsconvert.CollectTypes(tType, fnType) definition := tsconvert.GenerateFunctionDecl(name, tType, fnType, isAsync) // Register Function functionRegistry[name] = &functionImpl[A, R]{ name: name, fn: fn, types: types.All(), definition: definition, isAsync: isAsync, } } func GetFunctionDeclarations() string { // Lock Registry registryMutex.RLock() defer registryMutex.RUnlock() // Collect Type Definitions typeDefinitions := make(map[string]bool) var typeDefs []string var functionDecls []string for _, fn := range functionRegistry { for _, t := range fn.Types() { if !typeDefinitions[t] { typeDefinitions[t] = true typeDefs = append(typeDefs, t) } } functionDecls = append(functionDecls, fn.Definition()) } // Build Result result := strings.Join(typeDefs, "\n\n") if len(result) > 0 && len(functionDecls) > 0 { result += "\n\n" } result += strings.Join(functionDecls, "\n") return result } // GetTypeDeclarations returns all type declarations from all registered functions. // This is used for aggregating types across multiple functions. func GetTypeDeclarations() map[string]string { // Lock Registry registryMutex.RLock() defer registryMutex.RUnlock() // Collect All Types allTypes := make(map[string]string) for _, fn := range functionRegistry { for name, def := range fn.Types() { if existing, ok := allTypes[name]; ok && existing != def { // Type Conflict Detected - Skip continue } allTypes[name] = def } } return allTypes } func GetRegisteredFunctions() map[string]Function { // Lock Registry registryMutex.RLock() defer registryMutex.RUnlock() // Copy Registry result := make(map[string]Function, len(functionRegistry)) for k, v := range functionRegistry { result[k] = v } return result } func RegisterFunction[T Args, R any](name string, fn GoFunc[T, R]) { // Register Sync Function registerFunction(name, false, fn) } func RegisterAsyncFunction[T Args, R any](name string, fn GoFunc[T, R]) { // Register Async Function registerFunction(name, true, fn) }