module.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. package plugin
  2. import (
  3. "fmt"
  4. "html/template"
  5. "os"
  6. "path/filepath"
  7. "github.com/langgenius/dify-plugin-daemon/internal/utils/log"
  8. "github.com/langgenius/dify-plugin-daemon/pkg/entities/constants"
  9. "github.com/langgenius/dify-plugin-daemon/pkg/plugin_packager/decoder"
  10. )
  11. const TOOL_MODULE_TEMPLATE = `
  12. ========== {{.Identity.Name}} ==========
  13. Author: {{.Identity.Author}}
  14. Label: {{.Identity.Label.EnUS}}
  15. Description: {{.Description.Human.EnUS}}
  16. Parameters:
  17. {{- range .Parameters}}
  18. - Name: {{.Name}}
  19. Type: {{.Type}}
  20. Required: {{.Required}}
  21. Description: {{.HumanDescription.EnUS}}
  22. {{- if .Default}}
  23. Default: {{.Default}}
  24. {{- end}}
  25. {{- if .Options}}
  26. Options:
  27. {{- range .Options}}
  28. - Value: {{.Value}}
  29. Label: {{.Label.EnUS}}
  30. {{- end}}
  31. {{- end}}
  32. {{- end}}
  33. `
  34. const AGENT_MODULE_TEMPLATE = `
  35. ========== {{.Identity.Name}} ==========
  36. Author: {{.Identity.Author}}
  37. Label: {{.Identity.Label.EnUS}}
  38. Description: {{.Description.EnUS}}
  39. Parameters:
  40. {{- range .Parameters}}
  41. - Name: {{.Name}}
  42. Type: {{.Type}}
  43. Required: {{.Required}}
  44. {{- if .Default}}
  45. Default: {{.Default}}
  46. {{- end}}
  47. {{- end}}
  48. `
  49. const MODEL_MODULE_TEMPLATE = `
  50. ========== {{.Model}} ==========
  51. Name: {{.Model}}
  52. Type: {{.ModelType}}
  53. Label: {{.Label.EnUS}}
  54. Parameters:
  55. {{- range .ParameterRules}}
  56. - Name: {{.Name}}
  57. Type: {{.Type}}
  58. Required: {{.Required}}
  59. Description: {{.Help.EnUS}}
  60. {{- if .Default}}
  61. Default: {{.Default}}
  62. {{- end}}
  63. {{- if .Min}}
  64. Min: {{.Min}}
  65. {{- end}}
  66. {{- if .Max}}
  67. Max: {{.Max}}
  68. {{- end}}
  69. {{- if .Options}}
  70. Options: {{range .Options}}{{.}}, {{end}}
  71. {{- end}}
  72. {{- end}}
  73. `
  74. const ENDPOINT_MODULE_TEMPLATE = `
  75. ========== Endpoints ==========
  76. Path: {{.Path}}
  77. Method: {{.Method}}
  78. `
  79. const PLUGIN_MODULE_TEMPLATE = `
  80. ========== Plugin ==========
  81. Name: {{.Name}}
  82. Version: {{.Version}}
  83. Description: {{.Description.EnUS}}
  84. Author: {{.Author}}
  85. Icon: {{.Icon}}
  86. Tags: {{range .Tags}}{{.}}, {{end}}
  87. Category: {{.Category}}
  88. Resource:
  89. Memory: {{.Resource.Memory}} bytes
  90. Permissions:
  91. {{- if .Resource.Permission.Tool}}
  92. Tool: {{.Resource.Permission.Tool.Enabled}}
  93. {{- end}}
  94. {{- if .Resource.Permission.Model}}
  95. Model:
  96. Enabled: {{.Resource.Permission.Model.Enabled}}
  97. LLM: {{.Resource.Permission.Model.LLM}}
  98. TextEmbedding: {{.Resource.Permission.Model.TextEmbedding}}
  99. Rerank: {{.Resource.Permission.Model.Rerank}}
  100. TTS: {{.Resource.Permission.Model.TTS}}
  101. Speech2text: {{.Resource.Permission.Model.Speech2text}}
  102. Moderation: {{.Resource.Permission.Model.Moderation}}
  103. {{- end}}
  104. {{- if .Resource.Permission.Node}}
  105. Node: {{.Resource.Permission.Node.Enabled}}
  106. {{- end}}
  107. {{- if .Resource.Permission.Endpoint}}
  108. Endpoint: {{.Resource.Permission.Endpoint.Enabled}}
  109. {{- end}}
  110. {{- if .Resource.Permission.App}}
  111. App: {{.Resource.Permission.App.Enabled}}
  112. {{- end}}
  113. {{- if .Resource.Permission.Storage}}
  114. Storage:
  115. Enabled: {{.Resource.Permission.Storage.Enabled}}
  116. Size: {{.Resource.Permission.Storage.Size}} bytes
  117. {{- end}}
  118. `
  119. func ModuleList(pluginPath string) {
  120. var pluginDecoder decoder.PluginDecoder
  121. var err error
  122. stat, err := os.Stat(pluginPath)
  123. if err != nil {
  124. log.Error("failed to get plugin file stat: %s", err)
  125. return
  126. }
  127. if stat.IsDir() {
  128. pluginDecoder, err = decoder.NewFSPluginDecoder(pluginPath)
  129. } else {
  130. fileContent, err := os.ReadFile(pluginPath)
  131. if err != nil {
  132. log.Error("failed to read plugin file: %s", err)
  133. return
  134. }
  135. pluginDecoder, err = decoder.NewZipPluginDecoder(fileContent)
  136. if err != nil {
  137. log.Error("failed to create zip plugin decoder: %s", err)
  138. return
  139. }
  140. }
  141. if err != nil {
  142. log.Error("your plugin is not a valid plugin: %s", err)
  143. return
  144. }
  145. manifest, err := pluginDecoder.Manifest()
  146. if err != nil {
  147. log.Error("failed to get manifest: %s", err)
  148. return
  149. }
  150. if manifest.Tool != nil {
  151. for _, tool := range manifest.Tool.Tools {
  152. tmpl, err := template.New("tool").Parse(TOOL_MODULE_TEMPLATE)
  153. if err != nil {
  154. log.Error("failed to parse template: %s", err)
  155. return
  156. }
  157. err = tmpl.Execute(os.Stdout, tool)
  158. if err != nil {
  159. log.Error("failed to execute template: %s", err)
  160. return
  161. }
  162. }
  163. }
  164. if manifest.AgentStrategy != nil {
  165. for _, strategy := range manifest.AgentStrategy.Strategies {
  166. tmpl, err := template.New("agent").Parse(AGENT_MODULE_TEMPLATE)
  167. if err != nil {
  168. log.Error("failed to parse template: %s", err)
  169. return
  170. }
  171. err = tmpl.Execute(os.Stdout, strategy)
  172. if err != nil {
  173. log.Error("failed to execute template: %s", err)
  174. return
  175. }
  176. }
  177. }
  178. if manifest.Model != nil {
  179. for _, model := range manifest.Model.Models {
  180. tmpl, err := template.New("model").Parse(MODEL_MODULE_TEMPLATE)
  181. if err != nil {
  182. log.Error("failed to parse template: %s", err)
  183. return
  184. }
  185. err = tmpl.Execute(os.Stdout, model)
  186. if err != nil {
  187. log.Error("failed to execute template: %s", err)
  188. return
  189. }
  190. }
  191. }
  192. if manifest.Endpoint != nil {
  193. for _, endpoint := range manifest.Endpoint.Endpoints {
  194. tmpl, err := template.New("endpoint").Parse(ENDPOINT_MODULE_TEMPLATE)
  195. if err != nil {
  196. log.Error("failed to parse template: %s", err)
  197. return
  198. }
  199. err = tmpl.Execute(os.Stdout, endpoint)
  200. if err != nil {
  201. log.Error("failed to execute template: %s", err)
  202. return
  203. }
  204. }
  205. }
  206. }
  207. func ModuleAppendTools(pluginPath string) {
  208. decoder, err := decoder.NewFSPluginDecoder(pluginPath)
  209. if err != nil {
  210. log.Error("your plugin is not a valid plugin: %s", err)
  211. return
  212. }
  213. manifest, err := decoder.Manifest()
  214. if err != nil {
  215. log.Error("failed to get manifest: %s", err)
  216. return
  217. }
  218. if manifest.Tool != nil {
  219. log.Error("you have already declared tools in this plugin, " +
  220. "you can add new tool by modifying the `provider.yaml` file to add new tools, " +
  221. "this command is used to create new module that never been declared in this plugin.")
  222. return
  223. }
  224. if manifest.Model != nil {
  225. log.Error("model plugin dose not support declare tools.")
  226. return
  227. }
  228. if manifest.Plugins.Tools == nil {
  229. manifest.Plugins.Tools = []string{}
  230. }
  231. manifest.Plugins.Tools = append(manifest.Plugins.Tools, fmt.Sprintf("provider/%s.yaml", manifest.Name))
  232. if manifest.Meta.Runner.Language == constants.Python {
  233. if err := createPythonTool(pluginPath, &manifest); err != nil {
  234. log.Error("failed to create python tool: %s", err)
  235. return
  236. }
  237. if err := createPythonToolProvider(pluginPath, &manifest); err != nil {
  238. log.Error("failed to create python tool provider: %s", err)
  239. return
  240. }
  241. }
  242. // save manifest
  243. manifest_file := marshalYamlBytes(manifest.PluginDeclarationWithoutAdvancedFields)
  244. if err := writeFile(filepath.Join(pluginPath, "manifest.yaml"), string(manifest_file)); err != nil {
  245. log.Error("failed to save manifest: %s", err)
  246. return
  247. }
  248. log.Info("created tool module successfully")
  249. }
  250. func ModuleAppendEndpoints(pluginPath string) {
  251. decoder, err := decoder.NewFSPluginDecoder(pluginPath)
  252. if err != nil {
  253. log.Error("your plugin is not a valid plugin: %s", err)
  254. return
  255. }
  256. manifest, err := decoder.Manifest()
  257. if err != nil {
  258. log.Error("failed to get manifest: %s", err)
  259. return
  260. }
  261. if manifest.Endpoint != nil {
  262. log.Error("you have already declared endpoints in this plugin, " +
  263. "you can add new endpoint by modifying the `provider.yaml` file to add new endpoints, " +
  264. "this command is used to create new module that never been declared in this plugin.")
  265. return
  266. }
  267. if manifest.Model != nil {
  268. log.Error("model plugin dose not support declare endpoints.")
  269. return
  270. }
  271. if manifest.Plugins.Endpoints == nil {
  272. manifest.Plugins.Endpoints = []string{}
  273. }
  274. manifest.Plugins.Endpoints = append(manifest.Plugins.Endpoints, fmt.Sprintf("group/%s.yaml", manifest.Name))
  275. if manifest.Meta.Runner.Language == constants.Python {
  276. if err := createPythonEndpoint(pluginPath, &manifest); err != nil {
  277. log.Error("failed to create python endpoint: %s", err)
  278. return
  279. }
  280. if err := createPythonEndpointGroup(pluginPath, &manifest); err != nil {
  281. log.Error("failed to create python group: %s", err)
  282. return
  283. }
  284. }
  285. // save manifest
  286. manifest_file := marshalYamlBytes(manifest.PluginDeclarationWithoutAdvancedFields)
  287. if err := writeFile(filepath.Join(pluginPath, "manifest.yaml"), string(manifest_file)); err != nil {
  288. log.Error("failed to save manifest: %s", err)
  289. return
  290. }
  291. log.Info("created endpoint module successfully")
  292. }