package sdk import ( "context" "errors" "log/slog" commonv1 "code.icb4dc0.de/buildr/api/generated/common/v1" remotev1 "code.icb4dc0.de/buildr/api/generated/remote/v1" wasiv1 "code.icb4dc0.de/buildr/api/generated/wasi/v1" "code.icb4dc0.de/buildr/common/protocol" ) var ( defaultRegistry = NewTypeRegistry() startTaskWrapper = FuncExportWrapper[*remotev1.StartTaskRequest, *wasiv1.StartTaskResponse](StartTask) inventoryWrapper = FuncExportWrapper[*wasiv1.PluginInventoryRequest, *wasiv1.PluginInventoryResponse](GetInventory) helpForWrapper = FuncExportWrapper[*wasiv1.HelpRequest, *wasiv1.HelpResponse](HelpForModule) binaryNameWrapper = FuncExportWrapper[*wasiv1.BinaryNameRequest, *wasiv1.BinaryNameResponse](BinaryNameForModule) ) func Register(cat Category, moduleName string, factory Factory) { defaultRegistry.Add(cat, moduleName, factory) } func GetInventory(*wasiv1.PluginInventoryRequest) (*wasiv1.PluginInventoryResponse, error) { var inventory wasiv1.PluginInventoryResponse for _, t := range defaultRegistry.List() { m := defaultRegistry.Get(t.Category, t.Type) spec, err := protocol.Marshal(m) if err != nil { panic(err) } data, err := spec.MarshalVT() if err != nil { panic(err) } inventory.Specs = append(inventory.Specs, &wasiv1.PluginInventoryResponse_InventorySpec{ ModuleRef: &commonv1.ModuleReference{ ModuleCategory: t.Category, ModuleType: t.Type, }, EmptySpec: data, }) } return &inventory, nil } func StartTask(req *remotev1.StartTaskRequest) (*wasiv1.StartTaskResponse, error) { executor := NewExecutor(req.Buildr.Repo.Root, req.Buildr.OutDir, req.Buildr.BinDir) reference := req.GetReference().GetModule() module := defaultRegistry.Get(reference.GetModuleCategory(), reference.GetModuleType()) if err := protocol.Unmarshal(req.GetSpec(), module); err != nil { executor.logger.Error("Failed to unmarshal spec", slog.String("error", err.Error())) return nil, err } var startTaskResponse wasiv1.StartTaskResponse if err := executor.Run(context.Background(), module); err != nil { startTaskResponse.Error = err.Error() } return &startTaskResponse, nil } func HelpForModule(helpRequest *wasiv1.HelpRequest) (*wasiv1.HelpResponse, error) { module := defaultRegistry.Get(helpRequest.ModuleReference.ModuleCategory, helpRequest.ModuleReference.ModuleType) if module == nil { return nil, errors.New("unknown module") } helper, ok := module.(Helper) if !ok { return new(wasiv1.HelpResponse), nil } modHelp := helper.Help() helpResponse := &wasiv1.HelpResponse{ Name: modHelp.Name, Description: modHelp.Description, Examples: make([]*wasiv1.TaskExample, 0, len(modHelp.Examples)), } for _, e := range modHelp.Examples { modSpec, err := protocol.Marshal(e.Spec.Module) if err != nil { panic(err) } helpResponse.Examples = append(helpResponse.Examples, &wasiv1.TaskExample{ Name: e.Name, Description: e.Description, TaskSpec: &commonv1.TaskSpec{ ModuleName: e.Spec.ModuleName, Container: e.Spec.Container, OutputDir: e.Spec.OutputDir, ModuleSpec: modSpec, }, }) } return helpResponse, nil } func BinaryNameForModule(req *wasiv1.BinaryNameRequest) (*wasiv1.BinaryNameResponse, error) { module := defaultRegistry.Get(req.ModuleReference.ModuleCategory, req.ModuleReference.ModuleType) if module == nil { return nil, errors.New("unknown module") } namer, ok := module.(BinaryNamer) if !ok { return new(wasiv1.BinaryNameResponse), nil } if err := protocol.Unmarshal(req.GetSpec(), module); err != nil { return nil, err } return &wasiv1.BinaryNameResponse{ Name: namer.BinaryName(), }, nil } //export /buildr.rpc.v1.WasiExecutorService/PluginInventory func Inventory(ptr, size uint32) uint64 { return inventoryWrapper.Call(ptr, size) } //export /buildr.rpc.v1.WasiExecutorService/StartTask func Run(ptr, size uint32) uint64 { return startTaskWrapper.Call(ptr, size) } //export /buildr.rpc.v1.WasiExecutorService/Help func HelpFor(ptr, size uint32) uint64 { return helpForWrapper.Call(ptr, size) } //export /buildr.rpc.v1.WasiExecutorService/BinaryName func BinaryNameFor(ptr, size uint32) uint64 { return binaryNameWrapper.Call(ptr, size) }