install_to_local.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. package plugin_manager
  2. import (
  3. "io"
  4. "os"
  5. "path/filepath"
  6. "time"
  7. "github.com/langgenius/dify-plugin-daemon/internal/types/entities/plugin_entities"
  8. "github.com/langgenius/dify-plugin-daemon/internal/utils/routine"
  9. "github.com/langgenius/dify-plugin-daemon/internal/utils/stream"
  10. )
  11. // InstallToLocal installs a plugin to local
  12. func (p *PluginManager) InstallToLocal(
  13. plugin_path string,
  14. plugin_unique_identifier plugin_entities.PluginUniqueIdentifier,
  15. source string,
  16. meta map[string]any,
  17. ) (
  18. *stream.Stream[PluginInstallResponse], error,
  19. ) {
  20. plugin_file, err := os.Open(plugin_path)
  21. if err != nil {
  22. return nil, err
  23. }
  24. defer plugin_file.Close()
  25. installed_file_path := filepath.Join(p.pluginStoragePath, plugin_unique_identifier.String())
  26. installed_file, err := os.Create(installed_file_path)
  27. if err != nil {
  28. return nil, err
  29. }
  30. defer installed_file.Close()
  31. if _, err := io.Copy(installed_file, plugin_file); err != nil {
  32. return nil, err
  33. }
  34. runtime, err := p.launchLocal(installed_file_path)
  35. if err != nil {
  36. return nil, err
  37. }
  38. response := stream.NewStream[PluginInstallResponse](128)
  39. routine.Submit(func() {
  40. defer response.Close()
  41. ticker := time.NewTicker(time.Second * 5) // check heartbeat every 5 seconds
  42. defer ticker.Stop()
  43. timer := time.NewTimer(time.Second * 240) // timeout after 240 seconds
  44. defer timer.Stop()
  45. for {
  46. select {
  47. case <-ticker.C:
  48. // heartbeat
  49. response.Write(PluginInstallResponse{
  50. Event: PluginInstallEventInfo,
  51. Data: "Installing",
  52. })
  53. case <-timer.C:
  54. // timeout
  55. response.Write(PluginInstallResponse{
  56. Event: PluginInstallEventInfo,
  57. Data: "Timeout",
  58. })
  59. runtime.Stop()
  60. return
  61. case err := <-runtime.WaitLaunched():
  62. // launched
  63. if err != nil {
  64. response.Write(PluginInstallResponse{
  65. Event: PluginInstallEventError,
  66. Data: err.Error(),
  67. })
  68. runtime.Stop()
  69. return
  70. }
  71. response.Write(PluginInstallResponse{
  72. Event: PluginInstallEventDone,
  73. Data: "Installed",
  74. })
  75. return
  76. }
  77. }
  78. })
  79. return response, nil
  80. }