mirror of
https://github.com/langgenius/dify-plugin-daemon.git
synced 2026-07-22 17:56:00 -04:00
888ad788bc
* refactor: introduce local plugin control panel and cleanup environment setup process * fix: args * refactor: new local runtime * temp: stash work for refactor on RemotePluginServer * refactor: unify local runtime lifetime and sperate init environment process * chore: add missing files * stash * refactor: local plugin lifetime control * refactor: complete installation process of control panel * refactor: adapt service layer to new controlpanel * refactor: pluginManager.Install * fix: add routine wrap to InstallServerless, avoid blocking main thread * feat: reinstall serverless runtime * chore: add comments to Reinstall and update confusing naming * refactor: unify install plugin service * refactor: add labels to debugging runtime * refactor: add getters to plugin manager * refactor: split install service to decode/install_task/install service * ??? * refactor: adapt controllers * refactor: session write * refactor: session runtime * Refine install task orchestration (#501) * refactor: installing task * refactor cluster management, decouple lifetime management and cluster * fix cli test command * fix: cleanup TODO comments and implement GracefulStop for instance * feat: add logger to control panel * fix: multiple nil references * refactor: better lifetime control * refactor: better cycle interval * fix(LocalPluginRuntime): prevent returning err when it's not error * fix: avoid adding empty PipExtraArgs * fix: missing errors in Environment init * fix: add truncateMessage to avoid db explosion * cleanup: better lifecycle management * fix: init status at the beginning of installation * optimize: GracefulStop for pluginInstance * refactor: tests * refactor: centralize routine labels (#504) * cleanup: RoutineKey * fix: init routine pool * fix: correctly handle cluster register error * fix: memory leak * fix: add \n to instance write * fix(installer.go): set success to true after succeed for defer func * refactor * fix: missing cwd in testutils * fix: scaleup default runtime nums to 1 when testing * fix: localruntime appconfig in testing module * Update internal/core/local_runtime/load_balancing.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * fix: more efficiency implement in installer_local.go * fix: returns after failing in onDebuggingRuntimeDisconnected * fix: returns after failing in onDebuggingRuntimeDisconnected * fix: splits tests * refactor: naming * refactor: manifest.VersionX * fix: adapt SetDefault to tests * fix: enforce use constants in DBType * fix: generate * fix: linter * cleanup tests * refactor: change package to * cleanup: useless codes * Update internal/cluster/plugin.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * cleanup * refactor: decouple connection_key management from debugging_time * refactor: confused naming * feat: recycle resources to adapt to https://github.com/langgenius/dify-plugin-daemon/pull/500 * refactor: confusing redirecting * fix: support get serverless runtime * fix: race condition in Launching * fix: avoid ManifestValidate in first step of debugging handshake * fix: adding ReleaseAllLocks to finalizers * wtf: what a beautiful code * refactor: rename Stream.Async to Stream.Process * fix: kill process if daed instance was detected * fix: correctly handle failures * fix: consistence of difference interfaces * fix: add stacktrace to panic * fix: only trigger once event * fix: ensure plugin runtime was shutdown * feat: cleanup install tasks * fix: add scale logs --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
192 lines
4.6 KiB
Go
192 lines
4.6 KiB
Go
package plugin_entities
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha256"
|
|
"encoding/gob"
|
|
"encoding/hex"
|
|
"hash/fnv"
|
|
"time"
|
|
|
|
"github.com/langgenius/dify-plugin-daemon/internal/core/io_tunnel/access_types"
|
|
"github.com/langgenius/dify-plugin-daemon/pkg/entities"
|
|
)
|
|
|
|
type (
|
|
PluginRuntime struct {
|
|
State PluginRuntimeState `json:"state"`
|
|
Config PluginDeclaration `json:"config"`
|
|
}
|
|
|
|
PluginLifetime interface {
|
|
PluginBasicInfoInterface
|
|
PluginRuntimeSessionIOInterface
|
|
PluginClusterLifetime
|
|
}
|
|
|
|
PluginFullDuplexLifetime interface {
|
|
PluginLifetime
|
|
|
|
// before the plugin starts, it will call this method to initialize the environment
|
|
InitEnvironment() error
|
|
// Cleanup the plugin runtime
|
|
Cleanup()
|
|
// set the plugin to active
|
|
SetActive()
|
|
// set the plugin to launching
|
|
SetLaunching()
|
|
// set the plugin to restarting
|
|
SetRestarting()
|
|
// set the plugin to pending
|
|
SetPending()
|
|
// set the active time of the plugin
|
|
SetActiveAt(t time.Time)
|
|
// set the scheduled time of the plugin
|
|
SetScheduledAt(t time.Time)
|
|
}
|
|
|
|
PluginServerlessLifetime interface {
|
|
PluginLifetime
|
|
|
|
// before the plugin starts, it will call this method to initialize the environment
|
|
InitEnvironment() error
|
|
// UploadPlugin uploads the plugin to the AWS Lambda
|
|
UploadPlugin() error
|
|
}
|
|
|
|
PluginRuntimeSessionIOInterface interface {
|
|
PluginBasicInfoInterface
|
|
// Listen listens for messages from the plugin
|
|
Listen(session_id string) (*entities.Broadcast[SessionMessage], error)
|
|
// Write writes a message to the plugin
|
|
Write(session_id string, action access_types.PluginAccessAction, data []byte) error
|
|
}
|
|
|
|
PluginClusterLifetime interface {
|
|
// returns the runtime state of the plugin
|
|
RuntimeState() PluginRuntimeState
|
|
}
|
|
|
|
PluginBasicInfoInterface interface {
|
|
// returns the runtime type of the plugin
|
|
Type() PluginRuntimeType
|
|
// returns the plugin configuration
|
|
Configuration() *PluginDeclaration
|
|
// unique identity of the plugin
|
|
Identity() (PluginUniqueIdentifier, error)
|
|
// hashed identity of the plugin
|
|
HashedIdentity() (string, error)
|
|
// returns the checksum of the plugin
|
|
Checksum() (string, error)
|
|
}
|
|
)
|
|
|
|
func (r *PluginRuntime) Stopped() bool {
|
|
return r.State.Status == PLUGIN_RUNTIME_STATUS_STOPPED
|
|
}
|
|
|
|
func (r *PluginRuntime) Stop() {
|
|
r.State.Status = PLUGIN_RUNTIME_STATUS_STOPPED
|
|
}
|
|
|
|
func (r *PluginRuntime) Configuration() *PluginDeclaration {
|
|
return &r.Config
|
|
}
|
|
|
|
func HashedIdentity(identity string) string {
|
|
hash := sha256.New()
|
|
hash.Write([]byte(identity))
|
|
return hex.EncodeToString(hash.Sum(nil))
|
|
}
|
|
|
|
func (r *PluginRuntime) HashedIdentity() (string, error) {
|
|
return HashedIdentity(r.Config.Identity()), nil
|
|
}
|
|
|
|
func (r *PluginRuntime) RuntimeState() PluginRuntimeState {
|
|
return r.State
|
|
}
|
|
|
|
func (r *PluginRuntime) UpdateScheduledAt(t time.Time) {
|
|
r.State.ScheduledAt = &t
|
|
}
|
|
|
|
func (r *PluginRuntime) InitState() {
|
|
r.State = PluginRuntimeState{
|
|
Restarts: 0,
|
|
Status: PLUGIN_RUNTIME_STATUS_PENDING,
|
|
ActiveAt: nil,
|
|
StoppedAt: nil,
|
|
Verified: false,
|
|
ScheduledAt: nil,
|
|
Logs: []string{},
|
|
}
|
|
}
|
|
|
|
func (r *PluginRuntime) SetActive() {
|
|
r.State.Status = PLUGIN_RUNTIME_STATUS_ACTIVE
|
|
}
|
|
|
|
func (r *PluginRuntime) SetLaunching() {
|
|
r.State.Status = PLUGIN_RUNTIME_STATUS_LAUNCHING
|
|
}
|
|
|
|
func (r *PluginRuntime) SetRestarting() {
|
|
r.State.Status = PLUGIN_RUNTIME_STATUS_RESTARTING
|
|
}
|
|
|
|
func (r *PluginRuntime) SetPending() {
|
|
r.State.Status = PLUGIN_RUNTIME_STATUS_PENDING
|
|
}
|
|
|
|
func (r *PluginRuntime) SetActiveAt(t time.Time) {
|
|
r.State.ActiveAt = &t
|
|
}
|
|
|
|
func (r *PluginRuntime) SetScheduledAt(t time.Time) {
|
|
r.State.ScheduledAt = &t
|
|
}
|
|
|
|
type PluginRuntimeType string
|
|
|
|
const (
|
|
PLUGIN_RUNTIME_TYPE_LOCAL PluginRuntimeType = "local"
|
|
PLUGIN_RUNTIME_TYPE_REMOTE PluginRuntimeType = "remote"
|
|
PLUGIN_RUNTIME_TYPE_SERVERLESS PluginRuntimeType = "serverless"
|
|
)
|
|
|
|
type PluginRuntimeState struct {
|
|
Restarts int `json:"restarts"`
|
|
Status string `json:"status"`
|
|
WorkingPath string `json:"working_path"`
|
|
ActiveAt *time.Time `json:"active_at"`
|
|
StoppedAt *time.Time `json:"stopped_at"`
|
|
Verified bool `json:"verified"`
|
|
ScheduledAt *time.Time `json:"scheduled_at"`
|
|
Logs []string `json:"logs"`
|
|
}
|
|
|
|
func (s *PluginRuntimeState) Hash() (uint64, error) {
|
|
buf := bytes.Buffer{}
|
|
enc := gob.NewEncoder(&buf)
|
|
err := enc.Encode(s)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
j := fnv.New64a()
|
|
_, err = j.Write(buf.Bytes())
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return j.Sum64(), nil
|
|
}
|
|
|
|
const (
|
|
PLUGIN_RUNTIME_STATUS_ACTIVE = "active"
|
|
PLUGIN_RUNTIME_STATUS_LAUNCHING = "launching"
|
|
PLUGIN_RUNTIME_STATUS_STOPPED = "stopped"
|
|
PLUGIN_RUNTIME_STATUS_RESTARTING = "restarting"
|
|
PLUGIN_RUNTIME_STATUS_PENDING = "pending"
|
|
)
|