init.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. package init
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "time"
  7. tea "github.com/charmbracelet/bubbletea"
  8. "github.com/langgenius/dify-plugin-daemon/internal/types/entities/constants"
  9. "github.com/langgenius/dify-plugin-daemon/internal/types/entities/plugin_entities"
  10. "github.com/langgenius/dify-plugin-daemon/internal/utils/log"
  11. )
  12. func InitPlugin() {
  13. m := initialize()
  14. p := tea.NewProgram(m)
  15. if result, err := p.Run(); err != nil {
  16. fmt.Println("Error running program:", err)
  17. } else {
  18. if m, ok := result.(model); ok {
  19. if m.completed {
  20. m.createPlugin()
  21. }
  22. } else {
  23. log.Error("Error running program:", err)
  24. return
  25. }
  26. }
  27. }
  28. type subMenuKey string
  29. const (
  30. SUB_MENU_KEY_PROFILE subMenuKey = "profile"
  31. SUB_MENU_KEY_LANGUAGE subMenuKey = "language"
  32. SUB_MENU_KEY_PERMISSION subMenuKey = "permission"
  33. )
  34. type model struct {
  35. subMenus map[subMenuKey]subMenu
  36. subMenuSeq []subMenuKey
  37. currentSubMenu subMenuKey
  38. completed bool
  39. }
  40. func initialize() model {
  41. m := model{}
  42. m.subMenus = map[subMenuKey]subMenu{
  43. SUB_MENU_KEY_PROFILE: newProfile(),
  44. SUB_MENU_KEY_LANGUAGE: newLanguage(),
  45. SUB_MENU_KEY_PERMISSION: newPermission(),
  46. }
  47. m.currentSubMenu = SUB_MENU_KEY_PROFILE
  48. m.subMenuSeq = []subMenuKey{
  49. SUB_MENU_KEY_PROFILE,
  50. SUB_MENU_KEY_LANGUAGE,
  51. SUB_MENU_KEY_PERMISSION,
  52. }
  53. return m
  54. }
  55. func (m model) Init() tea.Cmd {
  56. return nil
  57. }
  58. func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
  59. currentSubMenu, event, cmd := m.subMenus[m.currentSubMenu].Update(msg)
  60. m.subMenus[m.currentSubMenu] = currentSubMenu
  61. switch event {
  62. case SUB_MENU_EVENT_NEXT:
  63. if m.currentSubMenu != m.subMenuSeq[len(m.subMenuSeq)-1] {
  64. // move the current sub menu to the next one
  65. for i, key := range m.subMenuSeq {
  66. if key == m.currentSubMenu {
  67. m.currentSubMenu = m.subMenuSeq[i+1]
  68. break
  69. }
  70. }
  71. } else {
  72. m.completed = true
  73. return m, tea.Quit
  74. }
  75. case SUB_MENU_EVENT_PREV:
  76. if m.currentSubMenu != m.subMenuSeq[0] {
  77. // move the current sub menu to the previous one
  78. for i, key := range m.subMenuSeq {
  79. if key == m.currentSubMenu {
  80. m.currentSubMenu = m.subMenuSeq[i-1]
  81. break
  82. }
  83. }
  84. }
  85. }
  86. return m, cmd
  87. }
  88. func (m model) View() string {
  89. return m.subMenus[m.currentSubMenu].View()
  90. }
  91. func (m model) createPlugin() {
  92. permission := m.subMenus[SUB_MENU_KEY_PERMISSION].(permission).Permission()
  93. manifest := &plugin_entities.PluginDeclaration{
  94. PluginDeclarationWithoutAdvancedFields: plugin_entities.PluginDeclarationWithoutAdvancedFields{
  95. Version: "0.0.1",
  96. Type: plugin_entities.PluginType,
  97. Author: m.subMenus[SUB_MENU_KEY_PROFILE].(profile).Author(),
  98. Name: m.subMenus[SUB_MENU_KEY_PROFILE].(profile).Name(),
  99. CreatedAt: time.Now(),
  100. Resource: plugin_entities.PluginResourceRequirement{
  101. Memory: 1024 * 1024 * 256, // 256MB
  102. Permission: &permission,
  103. },
  104. Label: plugin_entities.I18nObject{
  105. EnUS: m.subMenus[SUB_MENU_KEY_PROFILE].(profile).Name(),
  106. },
  107. },
  108. }
  109. manifest.Meta = plugin_entities.PluginMeta{
  110. Version: "0.0.1",
  111. Arch: []constants.Arch{
  112. constants.AMD64,
  113. constants.ARM64,
  114. },
  115. Runner: plugin_entities.PluginRunner{},
  116. }
  117. switch m.subMenus[SUB_MENU_KEY_LANGUAGE].(language).Language() {
  118. case constants.Python:
  119. manifest.Meta.Runner.Entrypoint = "main"
  120. manifest.Meta.Runner.Language = constants.Python
  121. manifest.Meta.Runner.Version = "3.10"
  122. default:
  123. log.Error("unsupported language: %s", m.subMenus[SUB_MENU_KEY_LANGUAGE].(language).Language())
  124. return
  125. }
  126. success := false
  127. clear := func() {
  128. if !success {
  129. os.RemoveAll(manifest.Name)
  130. }
  131. }
  132. defer clear()
  133. manifest_file := marshalYamlBytes(manifest)
  134. // create the plugin directory
  135. cwd, err := os.Getwd()
  136. if err != nil {
  137. log.Error("failed to get current working directory: %s", err)
  138. return
  139. }
  140. plugin_dir := filepath.Join(cwd, manifest.Name)
  141. if err := os.MkdirAll(plugin_dir, 0o755); err != nil {
  142. log.Error("failed to create plugin directory: %s", err)
  143. return
  144. }
  145. manifest_file_path := filepath.Join(plugin_dir, "manifest.yaml")
  146. if err := os.WriteFile(manifest_file_path, manifest_file, 0o644); err != nil {
  147. log.Error("failed to write manifest file: %s", err)
  148. return
  149. }
  150. err = createPythonEnvironment(plugin_dir, manifest.Meta.Runner.Entrypoint)
  151. if err != nil {
  152. log.Error("failed to create python environment: %s", err)
  153. return
  154. }
  155. success = true
  156. log.Info("plugin %s created successfully", manifest.Name)
  157. }