Browse Source

refactor: optimize plugin declaration caching and encoding (#34)

Yeuoly 7 months ago
parent
commit
b19140ca23

+ 4 - 0
go.mod

@@ -11,6 +11,7 @@ require (
 	github.com/aws/aws-sdk-go-v2/service/s3 v1.60.1
 	github.com/charmbracelet/bubbles v0.19.0
 	github.com/charmbracelet/bubbletea v1.1.0
+	github.com/fxamacker/cbor/v2 v2.7.0
 	github.com/getsentry/sentry-go v0.30.0
 	github.com/gin-contrib/gzip v1.0.1
 	github.com/go-git/go-git v4.7.0+incompatible
@@ -18,6 +19,7 @@ require (
 	github.com/redis/go-redis/v9 v9.5.3
 	github.com/spf13/cobra v1.8.1
 	github.com/spf13/viper v1.19.0
+	github.com/vmihailenco/msgpack/v5 v5.4.1
 	github.com/xeipuuv/gojsonschema v1.2.0
 	gorm.io/gorm v1.25.11
 )
@@ -72,6 +74,8 @@ require (
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/src-d/gcfg v1.4.0 // indirect
 	github.com/subosito/gotenv v1.6.0 // indirect
+	github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
+	github.com/x448/float16 v0.8.4 // indirect
 	github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
 	github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect

+ 8 - 0
go.sum

@@ -81,6 +81,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
 github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
 github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
+github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
+github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
 github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I=
 github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s=
 github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0=
@@ -247,6 +249,12 @@ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65E
 github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
 github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
+github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
+github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
+github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
+github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
+github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
 github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
 github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
 github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=

+ 2 - 2
internal/core/plugin_manager/install_to_serverless.go

@@ -24,7 +24,8 @@ func (p *PluginManager) InstallToAWSFromPkg(
 	if err != nil {
 		return nil, err
 	}
-	declaration, err := decoder.Manifest()
+	// check valid manifest
+	_, err = decoder.Manifest()
 	if err != nil {
 		return nil, err
 	}
@@ -80,7 +81,6 @@ func (p *PluginManager) InstallToAWSFromPkg(
 						FunctionURL:            functionUrl,
 						FunctionName:           functionName,
 						PluginUniqueIdentifier: uniqueIdentity.String(),
-						Declaration:            declaration,
 					}
 					err = db.Create(serverlessModel)
 					if err != nil {

+ 1 - 1
internal/core/plugin_manager/manager.go

@@ -256,6 +256,6 @@ func (p *PluginManager) GetDeclaration(
 	*plugin_entities.PluginDeclaration, error,
 ) {
 	return helper.CombinedGetPluginDeclaration(
-		plugin_unique_identifier, tenant_id, runtime_type,
+		plugin_unique_identifier, runtime_type,
 	)
 }

+ 4 - 2
internal/core/plugin_manager/serverless.go

@@ -9,6 +9,7 @@ import (
 	"github.com/langgenius/dify-plugin-daemon/internal/db"
 	"github.com/langgenius/dify-plugin-daemon/internal/types/models"
 	"github.com/langgenius/dify-plugin-daemon/internal/utils/cache"
+	"github.com/langgenius/dify-plugin-daemon/internal/utils/cache/helper"
 	"github.com/langgenius/dify-plugin-daemon/pkg/entities/plugin_entities"
 )
 
@@ -30,11 +31,12 @@ func (p *PluginManager) getServerlessPluginRuntime(
 		return nil, err
 	}
 
-	declaration := model.Declaration
+	// FIXME: get declaration
+	declaration, err := helper.CombinedGetPluginDeclaration(identity, plugin_entities.PLUGIN_RUNTIME_TYPE_SERVERLESS)
 
 	// init runtime entity
 	runtimeEntity := plugin_entities.PluginRuntime{
-		Config: declaration,
+		Config: *declaration,
 	}
 	runtimeEntity.InitState()
 

+ 38 - 1
internal/db/init.go

@@ -77,7 +77,7 @@ func initDifyPluginDB(host string, port int, db_name string, user string, pass s
 }
 
 func autoMigrate() error {
-	return DifyPluginDB.AutoMigrate(
+	err := DifyPluginDB.AutoMigrate(
 		models.Plugin{},
 		models.PluginInstallation{},
 		models.PluginDeclaration{},
@@ -89,6 +89,43 @@ func autoMigrate() error {
 		models.TenantStorage{},
 		models.AgentStrategyInstallation{},
 	)
+
+	if err != nil {
+		return err
+	}
+
+	// check if "declaration" table exists in Plugin/ServerlessRuntime/ToolInstallation/AIModelInstallation/AgentStrategyInstallation
+	// delete the column if exists
+	deleteDeclarationColumn := func(model any) error {
+		if DifyPluginDB.Migrator().HasColumn(model, "declaration") {
+			if err := DifyPluginDB.Migrator().DropColumn(model, "declaration"); err != nil {
+				return err
+			}
+		}
+		return nil
+	}
+
+	if err := deleteDeclarationColumn(&models.Plugin{}); err != nil {
+		return err
+	}
+
+	if err := deleteDeclarationColumn(&models.ServerlessRuntime{}); err != nil {
+		return err
+	}
+
+	if err := deleteDeclarationColumn(&models.ToolInstallation{}); err != nil {
+		return err
+	}
+
+	if err := deleteDeclarationColumn(&models.AIModelInstallation{}); err != nil {
+		return err
+	}
+
+	if err := deleteDeclarationColumn(&models.AgentStrategyInstallation{}); err != nil {
+		return err
+	}
+
+	return nil
 }
 
 func Init(config *app.Config) {

+ 1 - 1
internal/server/controllers/plugins.go

@@ -198,7 +198,7 @@ func FetchPluginManifest(c *gin.Context) {
 		TenantID               string                                 `uri:"tenant_id" validate:"required"`
 		PluginUniqueIdentifier plugin_entities.PluginUniqueIdentifier `form:"plugin_unique_identifier" validate:"required,plugin_unique_identifier"`
 	}) {
-		c.JSON(http.StatusOK, service.FetchPluginManifest(request.TenantID, request.PluginUniqueIdentifier))
+		c.JSON(http.StatusOK, service.FetchPluginManifest(request.PluginUniqueIdentifier))
 	})
 }
 

+ 10 - 11
internal/server/http_server.go

@@ -6,7 +6,6 @@ import (
 	"net/http"
 	"time"
 
-	"github.com/gin-contrib/gzip"
 	"github.com/gin-gonic/gin"
 	"github.com/langgenius/dify-plugin-daemon/internal/core/plugin_daemon/backwards_invocation/transaction"
 	"github.com/langgenius/dify-plugin-daemon/internal/server/controllers"
@@ -137,8 +136,8 @@ func (app *App) endpointManagementGroup(group *gin.RouterGroup) {
 }
 
 func (app *App) pluginManagementGroup(group *gin.RouterGroup, config *app.Config) {
-	group.POST("/install/upload/package", gzip.Gzip(gzip.DefaultCompression), controllers.UploadPlugin(config))
-	group.POST("/install/upload/bundle", gzip.Gzip(gzip.DefaultCompression), controllers.UploadBundle(config))
+	group.POST("/install/upload/package", controllers.UploadPlugin(config))
+	group.POST("/install/upload/bundle", controllers.UploadBundle(config))
 	group.POST("/install/identifiers", controllers.InstallPluginFromIdentifiers(config))
 	group.POST("/install/upgrade", controllers.UpgradePlugin(config))
 	group.GET("/install/tasks/:id", controllers.FetchPluginInstallationTask)
@@ -146,22 +145,22 @@ func (app *App) pluginManagementGroup(group *gin.RouterGroup, config *app.Config
 	group.POST("/install/tasks/:id/delete", controllers.DeletePluginInstallationTask)
 	group.POST("/install/tasks/:id/delete/*identifier", controllers.DeletePluginInstallationItemFromTask)
 	group.GET("/install/tasks", controllers.FetchPluginInstallationTasks)
-	group.GET("/fetch/manifest", gzip.Gzip(gzip.DefaultCompression), controllers.FetchPluginManifest)
+	group.GET("/fetch/manifest", controllers.FetchPluginManifest)
 	group.GET("/fetch/identifier", controllers.FetchPluginFromIdentifier)
 	group.POST("/uninstall", controllers.UninstallPlugin)
-	group.GET("/list", gzip.Gzip(gzip.DefaultCompression), controllers.ListPlugins)
+	group.GET("/list", controllers.ListPlugins)
 	group.POST("/installation/fetch/batch", controllers.BatchFetchPluginInstallationByIDs)
 	group.POST("/installation/missing", controllers.FetchMissingPluginInstallations)
-	group.GET("/models", gzip.Gzip(gzip.DefaultCompression), controllers.ListModels)
-	group.GET("/tools", gzip.Gzip(gzip.DefaultCompression), controllers.ListTools)
-	group.GET("/tool", gzip.Gzip(gzip.DefaultCompression), controllers.GetTool)
+	group.GET("/models", controllers.ListModels)
+	group.GET("/tools", controllers.ListTools)
+	group.GET("/tool", controllers.GetTool)
 	group.POST("/tools/check_existence", controllers.CheckToolExistence)
-	group.GET("/agent_strategies", gzip.Gzip(gzip.DefaultCompression), controllers.ListAgentStrategies)
-	group.GET("/agent_strategy", gzip.Gzip(gzip.DefaultCompression), controllers.GetAgentStrategy)
+	group.GET("/agent_strategies", controllers.ListAgentStrategies)
+	group.GET("/agent_strategy", controllers.GetAgentStrategy)
 }
 
 func (app *App) pluginAssetGroup(group *gin.RouterGroup) {
-	group.GET("/:id", gzip.Gzip(gzip.DefaultCompression), controllers.GetAsset)
+	group.GET("/:id", controllers.GetAsset)
 }
 
 func (app *App) pprofGroup(group *gin.RouterGroup, config *app.Config) {

+ 10 - 3
internal/service/install_plugin.go

@@ -64,7 +64,6 @@ func InstallPluginRuntimeToTenant(
 		// fetch plugin declaration first, before installing, we need to ensure pkg is uploaded
 		pluginDeclaration, err := helper.CombinedGetPluginDeclaration(
 			pluginUniqueIdentifier,
-			tenant_id,
 			runtimeType,
 		)
 		if err != nil {
@@ -125,7 +124,6 @@ func InstallPluginRuntimeToTenant(
 
 		declaration, err := helper.CombinedGetPluginDeclaration(
 			pluginUniqueIdentifier,
-			tenant_id,
 			runtimeType,
 		)
 		if err != nil {
@@ -385,7 +383,6 @@ func UpgradePlugin(
 				tenant_id,
 				original_plugin_unique_identifier,
 				new_plugin_unique_identifier,
-				declaration,
 				plugin_entities.PluginRuntimeType(installation.RuntimeType),
 				source,
 				meta,
@@ -574,11 +571,21 @@ func UninstallPlugin(
 		return exception.UniqueIdentifierError(err).ToResponse()
 	}
 
+	// get declaration
+	declaration, err := helper.CombinedGetPluginDeclaration(
+		pluginUniqueIdentifier,
+		plugin_entities.PluginRuntimeType(installation.RuntimeType),
+	)
+	if err != nil {
+		return exception.InternalServerError(err).ToResponse()
+	}
+
 	// Uninstall the plugin
 	deleteResponse, err := curd.UninstallPlugin(
 		tenant_id,
 		pluginUniqueIdentifier,
 		installation.ID,
+		declaration,
 	)
 	if err != nil {
 		return exception.InternalServerError(fmt.Errorf("failed to uninstall plugin: %s", err.Error())).ToResponse()

+ 10 - 1
internal/service/install_service/state.go

@@ -6,6 +6,7 @@ import (
 	"github.com/langgenius/dify-plugin-daemon/internal/db"
 	"github.com/langgenius/dify-plugin-daemon/internal/types/models"
 	"github.com/langgenius/dify-plugin-daemon/internal/types/models/curd"
+	"github.com/langgenius/dify-plugin-daemon/internal/utils/cache/helper"
 	"github.com/langgenius/dify-plugin-daemon/internal/utils/strings"
 	"github.com/langgenius/dify-plugin-daemon/pkg/entities/plugin_entities"
 	"gorm.io/gorm"
@@ -46,8 +47,16 @@ func UninstallPlugin(
 	plugin_unique_identifier plugin_entities.PluginUniqueIdentifier,
 	install_type plugin_entities.PluginRuntimeType,
 ) error {
+	// get declaration
+	declaration, err := helper.CombinedGetPluginDeclaration(
+		plugin_unique_identifier,
+		install_type,
+	)
+	if err != nil {
+		return err
+	}
 	// delete the plugin from db
-	_, err := curd.UninstallPlugin(tenant_id, plugin_unique_identifier, installation_id)
+	_, err = curd.UninstallPlugin(tenant_id, plugin_unique_identifier, installation_id, declaration)
 	if err != nil {
 		return err
 	}

+ 155 - 7
internal/service/manage_plugin.go

@@ -55,7 +55,6 @@ func ListPlugins(tenant_id string, page int, page_size int) *entities.Response {
 
 		pluginDeclaration, err := helper.CombinedGetPluginDeclaration(
 			pluginUniqueIdentifier,
-			tenant_id,
 			plugin_entities.PluginRuntimeType(plugin_installation.RuntimeType),
 		)
 		if err != nil {
@@ -122,7 +121,6 @@ func BatchFetchPluginInstallationByIDs(tenant_id string, plugin_ids []string) *e
 
 		pluginDeclaration, err := helper.CombinedGetPluginDeclaration(
 			pluginUniqueIdentifier,
-			tenant_id,
 			plugin_entities.PluginRuntimeType(plugin_installation.RuntimeType),
 		)
 		if err != nil {
@@ -198,6 +196,12 @@ func FetchMissingPluginInstallations(tenant_id string, plugin_unique_identifiers
 }
 
 func ListTools(tenant_id string, page int, page_size int) *entities.Response {
+	type Tool struct {
+		models.ToolInstallation // pointer to avoid deep copy
+
+		Declaration *plugin_entities.ToolProviderDeclaration `json:"declaration"`
+	}
+
 	providers, err := db.GetAll[models.ToolInstallation](
 		db.Equal("tenant_id", tenant_id),
 		db.Page(page, page_size),
@@ -207,10 +211,44 @@ func ListTools(tenant_id string, page int, page_size int) *entities.Response {
 		return exception.InternalServerError(err).ToResponse()
 	}
 
-	return entities.NewSuccessResponse(providers)
+	data := make([]Tool, 0, len(providers))
+
+	for _, provider := range providers {
+		// check if plugin id starts with uuid
+		// split by uuid length
+		uniqueIdentifier := plugin_entities.PluginUniqueIdentifier(provider.PluginUniqueIdentifier)
+		var runtimeType plugin_entities.PluginRuntimeType
+		if uniqueIdentifier.RemoteLike() {
+			runtimeType = plugin_entities.PLUGIN_RUNTIME_TYPE_REMOTE
+		} else {
+			runtimeType = plugin_entities.PLUGIN_RUNTIME_TYPE_LOCAL
+		}
+
+		declaration, err := helper.CombinedGetPluginDeclaration(
+			uniqueIdentifier,
+			runtimeType,
+		)
+
+		if err != nil {
+			return exception.InternalServerError(err).ToResponse()
+		}
+
+		data = append(data, Tool{
+			ToolInstallation: provider,
+			Declaration:      declaration.Tool,
+		})
+	}
+
+	return entities.NewSuccessResponse(data)
 }
 
 func ListModels(tenant_id string, page int, page_size int) *entities.Response {
+	type AIModel struct {
+		models.AIModelInstallation // pointer to avoid deep copy
+
+		Declaration *plugin_entities.ModelProviderDeclaration `json:"declaration"`
+	}
+
 	providers, err := db.GetAll[models.AIModelInstallation](
 		db.Equal("tenant_id", tenant_id),
 		db.Page(page, page_size),
@@ -220,10 +258,42 @@ func ListModels(tenant_id string, page int, page_size int) *entities.Response {
 		return exception.InternalServerError(err).ToResponse()
 	}
 
-	return entities.NewSuccessResponse(providers)
+	data := make([]AIModel, 0, len(providers))
+
+	for _, provider := range providers {
+		uniqueIdentifier := plugin_entities.PluginUniqueIdentifier(provider.PluginUniqueIdentifier)
+		var runtimeType plugin_entities.PluginRuntimeType
+		if uniqueIdentifier.RemoteLike() {
+			runtimeType = plugin_entities.PLUGIN_RUNTIME_TYPE_REMOTE
+		} else {
+			runtimeType = plugin_entities.PLUGIN_RUNTIME_TYPE_LOCAL
+		}
+
+		declaration, err := helper.CombinedGetPluginDeclaration(
+			uniqueIdentifier,
+			runtimeType,
+		)
+
+		if err != nil {
+			return exception.InternalServerError(err).ToResponse()
+		}
+
+		data = append(data, AIModel{
+			AIModelInstallation: provider,
+			Declaration:         declaration.Model,
+		})
+	}
+
+	return entities.NewSuccessResponse(data)
 }
 
 func GetTool(tenant_id string, plugin_id string, provider string) *entities.Response {
+	type Tool struct {
+		models.ToolInstallation // pointer to avoid deep copy
+
+		Declaration *plugin_entities.ToolProviderDeclaration `json:"declaration"`
+	}
+
 	// try get tool
 	tool, err := db.GetOne[models.ToolInstallation](
 		db.Equal("tenant_id", tenant_id),
@@ -242,7 +312,27 @@ func GetTool(tenant_id string, plugin_id string, provider string) *entities.Resp
 		return exception.ErrPluginNotFound().ToResponse()
 	}
 
-	return entities.NewSuccessResponse(tool)
+	uniqueIdentifier := plugin_entities.PluginUniqueIdentifier(tool.PluginUniqueIdentifier)
+	var runtimeType plugin_entities.PluginRuntimeType
+	if uniqueIdentifier.RemoteLike() {
+		runtimeType = plugin_entities.PLUGIN_RUNTIME_TYPE_REMOTE
+	} else {
+		runtimeType = plugin_entities.PLUGIN_RUNTIME_TYPE_LOCAL
+	}
+
+	declaration, err := helper.CombinedGetPluginDeclaration(
+		uniqueIdentifier,
+		runtimeType,
+	)
+
+	if err != nil {
+		return exception.InternalServerError(err).ToResponse()
+	}
+
+	return entities.NewSuccessResponse(Tool{
+		ToolInstallation: tool,
+		Declaration:      declaration.Tool,
+	})
 }
 
 type RequestCheckToolExistence struct {
@@ -281,6 +371,12 @@ func CheckToolExistence(tenantId string, providerIds []RequestCheckToolExistence
 }
 
 func ListAgentStrategies(tenant_id string, page int, page_size int) *entities.Response {
+	type AgentStrategy struct {
+		models.AgentStrategyInstallation // pointer to avoid deep copy
+
+		Declaration *plugin_entities.AgentStrategyProviderDeclaration `json:"declaration"`
+	}
+
 	providers, err := db.GetAll[models.AgentStrategyInstallation](
 		db.Equal("tenant_id", tenant_id),
 		db.Page(page, page_size),
@@ -290,10 +386,42 @@ func ListAgentStrategies(tenant_id string, page int, page_size int) *entities.Re
 		return exception.InternalServerError(err).ToResponse()
 	}
 
-	return entities.NewSuccessResponse(providers)
+	data := make([]AgentStrategy, 0, len(providers))
+
+	for _, provider := range providers {
+		uniqueIdentifier := plugin_entities.PluginUniqueIdentifier(provider.PluginUniqueIdentifier)
+		var runtimeType plugin_entities.PluginRuntimeType
+		if uniqueIdentifier.RemoteLike() {
+			runtimeType = plugin_entities.PLUGIN_RUNTIME_TYPE_REMOTE
+		} else {
+			runtimeType = plugin_entities.PLUGIN_RUNTIME_TYPE_LOCAL
+		}
+
+		declaration, err := helper.CombinedGetPluginDeclaration(
+			uniqueIdentifier,
+			runtimeType,
+		)
+
+		if err != nil {
+			return exception.InternalServerError(err).ToResponse()
+		}
+
+		data = append(data, AgentStrategy{
+			AgentStrategyInstallation: provider,
+			Declaration:               declaration.AgentStrategy,
+		})
+	}
+
+	return entities.NewSuccessResponse(data)
 }
 
 func GetAgentStrategy(tenant_id string, plugin_id string, provider string) *entities.Response {
+	type AgentStrategy struct {
+		models.AgentStrategyInstallation // pointer to avoid deep copy
+
+		Declaration *plugin_entities.AgentStrategyProviderDeclaration `json:"declaration"`
+	}
+
 	agent_strategy, err := db.GetOne[models.AgentStrategyInstallation](
 		db.Equal("tenant_id", tenant_id),
 		db.Equal("plugin_id", plugin_id),
@@ -311,5 +439,25 @@ func GetAgentStrategy(tenant_id string, plugin_id string, provider string) *enti
 		return exception.ErrPluginNotFound().ToResponse()
 	}
 
-	return entities.NewSuccessResponse(agent_strategy)
+	uniqueIdentifier := plugin_entities.PluginUniqueIdentifier(agent_strategy.PluginUniqueIdentifier)
+	var runtimeType plugin_entities.PluginRuntimeType
+	if uniqueIdentifier.RemoteLike() {
+		runtimeType = plugin_entities.PLUGIN_RUNTIME_TYPE_REMOTE
+	} else {
+		runtimeType = plugin_entities.PLUGIN_RUNTIME_TYPE_LOCAL
+	}
+
+	declaration, err := helper.CombinedGetPluginDeclaration(
+		uniqueIdentifier,
+		runtimeType,
+	)
+
+	if err != nil {
+		return exception.InternalServerError(err).ToResponse()
+	}
+
+	return entities.NewSuccessResponse(AgentStrategy{
+		AgentStrategyInstallation: agent_strategy,
+		Declaration:               declaration.AgentStrategy,
+	})
 }

+ 1 - 2
internal/service/plugin_decoder.go

@@ -162,7 +162,6 @@ func UploadPluginBundle(
 }
 
 func FetchPluginManifest(
-	tenant_id string,
 	pluginUniqueIdentifier plugin_entities.PluginUniqueIdentifier,
 ) *entities.Response {
 	runtimeType := plugin_entities.PLUGIN_RUNTIME_TYPE_LOCAL
@@ -171,7 +170,7 @@ func FetchPluginManifest(
 	}
 
 	pluginManifestCache, err := helper.CombinedGetPluginDeclaration(
-		pluginUniqueIdentifier, tenant_id, runtimeType,
+		pluginUniqueIdentifier, runtimeType,
 	)
 	if err == helper.ErrPluginNotFound {
 		return exception.BadRequestError(errors.New("plugin not found")).ToResponse()

+ 0 - 2
internal/service/setup_endpoint.go

@@ -35,7 +35,6 @@ func SetupEndpoint(
 	// try get plugin
 	pluginDeclaration, err := helper.CombinedGetPluginDeclaration(
 		pluginUniqueIdentifier,
-		tenant_id,
 		plugin_entities.PluginRuntimeType(installation.RuntimeType),
 	)
 
@@ -169,7 +168,6 @@ func UpdateEndpoint(endpoint_id string, tenant_id string, user_id string, name s
 	// get plugin
 	pluginDeclaration, err := helper.CombinedGetPluginDeclaration(
 		pluginUniqueIdentifier,
-		tenant_id,
 		plugin_entities.PluginRuntimeType(installation.RuntimeType),
 	)
 	if err != nil {

+ 11 - 0
internal/types/exception/factory.go

@@ -1,5 +1,11 @@
 package exception
 
+import (
+	"runtime/debug"
+
+	"github.com/langgenius/dify-plugin-daemon/internal/utils/log"
+)
+
 const (
 	PluginDaemonInternalServerError   = "PluginDaemonInternalServerError"
 	PluginDaemonBadRequestError       = "PluginDaemonBadRequestError"
@@ -16,6 +22,11 @@ const (
 )
 
 func InternalServerError(err error) PluginDaemonError {
+	// log the error
+	// get traceback
+	traceback := string(debug.Stack())
+	log.Error("PluginDaemonInternalServerError: %v\n%s", err, traceback)
+
 	return ErrorWithTypeAndCode(err.Error(), PluginDaemonInternalServerError, -500)
 }
 

+ 4 - 7
internal/types/models/agent.go

@@ -1,12 +1,9 @@
 package models
 
-import "github.com/langgenius/dify-plugin-daemon/pkg/entities/plugin_entities"
-
 type AgentStrategyInstallation struct {
 	Model
-	TenantID               string                                           `json:"tenant_id" gorm:"column:tenant_id;type:uuid;index;not null"`
-	Provider               string                                           `json:"provider" gorm:"column:provider;size:127;index;not null"`
-	PluginUniqueIdentifier string                                           `json:"plugin_unique_identifier" gorm:"index;size:255"`
-	PluginID               string                                           `json:"plugin_id" gorm:"index;size:255"`
-	Declaration            plugin_entities.AgentStrategyProviderDeclaration `json:"declaration,inline" gorm:"serializer:json;type:text;size:65535;not null"`
+	TenantID               string `json:"tenant_id" gorm:"column:tenant_id;type:uuid;index;not null"`
+	Provider               string `json:"provider" gorm:"column:provider;size:127;index;not null"`
+	PluginUniqueIdentifier string `json:"plugin_unique_identifier" gorm:"index;size:255"`
+	PluginID               string `json:"plugin_id" gorm:"index;size:255"`
 }

+ 1 - 7
internal/types/models/curd/atomic.go

@@ -52,7 +52,6 @@ func InstallPlugin(
 				PluginUniqueIdentifier: plugin_unique_identifier.String(),
 				InstallType:            install_type,
 				Refers:                 1,
-				Declaration:            *declaration,
 			}
 
 			err := db.Create(plugin, tx)
@@ -107,7 +106,6 @@ func InstallPlugin(
 				PluginUniqueIdentifier: pluginToBeReturns.PluginUniqueIdentifier,
 				TenantID:               tenant_id,
 				Provider:               declaration.Tool.Identity.Name,
-				Declaration:            *declaration.Tool,
 			}
 
 			err := db.Create(toolInstallation, tx)
@@ -123,7 +121,6 @@ func InstallPlugin(
 				PluginUniqueIdentifier: pluginToBeReturns.PluginUniqueIdentifier,
 				TenantID:               tenant_id,
 				Provider:               declaration.AgentStrategy.Identity.Name,
-				Declaration:            *declaration.AgentStrategy,
 			}
 
 			err := db.Create(agentStrategyInstallation, tx)
@@ -139,7 +136,6 @@ func InstallPlugin(
 				PluginUniqueIdentifier: pluginToBeReturns.PluginUniqueIdentifier,
 				TenantID:               tenant_id,
 				Provider:               declaration.Model.Provider,
-				Declaration:            *declaration.Model,
 			}
 
 			err := db.Create(modelInstallation, tx)
@@ -174,6 +170,7 @@ func UninstallPlugin(
 	tenant_id string,
 	plugin_unique_identifier plugin_entities.PluginUniqueIdentifier,
 	installation_id string,
+	declaration *plugin_entities.PluginDeclaration,
 ) (*DeletePluginResponse, error) {
 	var pluginToBeReturns *models.Plugin
 	var installationToBeReturns *models.PluginInstallation
@@ -231,7 +228,6 @@ func UninstallPlugin(
 		}
 
 		// delete tool installation
-		declaration := p.Declaration
 		if declaration.Tool != nil {
 			toolInstallation := &models.ToolInstallation{
 				PluginID:               pluginToBeReturns.PluginID,
@@ -309,7 +305,6 @@ func UpgradePlugin(
 	tenant_id string,
 	original_plugin_unique_identifier plugin_entities.PluginUniqueIdentifier,
 	new_plugin_unique_identifier plugin_entities.PluginUniqueIdentifier,
-	new_declaration *plugin_entities.PluginDeclaration,
 	install_type plugin_entities.PluginRuntimeType,
 	source string,
 	meta map[string]any,
@@ -343,7 +338,6 @@ func UpgradePlugin(
 				PluginUniqueIdentifier: new_plugin_unique_identifier.String(),
 				InstallType:            install_type,
 				Refers:                 0,
-				Declaration:            *new_declaration,
 				ManifestType:           manifest_entities.PluginType,
 			}
 

+ 4 - 7
internal/types/models/model.go

@@ -1,12 +1,9 @@
 package models
 
-import "github.com/langgenius/dify-plugin-daemon/pkg/entities/plugin_entities"
-
 type AIModelInstallation struct {
 	Model
-	Provider               string                                   `json:"provider" gorm:"column:provider;size:127;index;not null"`
-	TenantID               string                                   `json:"tenant_id" gorm:"column:tenant_id;type:uuid;index;not null"`
-	PluginUniqueIdentifier string                                   `json:"plugin_unique_identifier" gorm:"index;size:255"`
-	PluginID               string                                   `json:"plugin_id" gorm:"index;size:255"`
-	Declaration            plugin_entities.ModelProviderDeclaration `json:"declaration" gorm:"serializer:json;type:text;size:65535;not null"`
+	Provider               string `json:"provider" gorm:"column:provider;size:127;index;not null"`
+	TenantID               string `json:"tenant_id" gorm:"column:tenant_id;type:uuid;index;not null"`
+	PluginUniqueIdentifier string `json:"plugin_unique_identifier" gorm:"index;size:255"`
+	PluginID               string `json:"plugin_id" gorm:"index;size:255"`
 }

+ 10 - 11
internal/types/models/plugin.go

@@ -10,11 +10,11 @@ type Plugin struct {
 	// PluginUniqueIdentifier is a unique identifier for the plugin, it contains version and checksum
 	PluginUniqueIdentifier string `json:"plugin_unique_identifier" gorm:"index;size:255"`
 	// PluginID is the id of the plugin, only plugin name is considered
-	PluginID     string                             `json:"id" gorm:"index;size:255"`
-	Refers       int                                `json:"refers" gorm:"default:0"`
-	InstallType  plugin_entities.PluginRuntimeType  `json:"install_type" gorm:"size:127;index"`
-	ManifestType manifest_entities.DifyManifestType `json:"manifest_type" gorm:"size:127"`
-	Declaration  plugin_entities.PluginDeclaration  `json:"declaration" gorm:"serializer:json;type:text;size:65535"`
+	PluginID          string                             `json:"id" gorm:"index;size:255"`
+	Refers            int                                `json:"refers" gorm:"default:0"`
+	InstallType       plugin_entities.PluginRuntimeType  `json:"install_type" gorm:"size:127;index"`
+	ManifestType      manifest_entities.DifyManifestType `json:"manifest_type" gorm:"size:127"`
+	RemoteDeclaration plugin_entities.PluginDeclaration  `json:"remote_declaration" gorm:"serializer:json;type:text;size:65535"` // enabled when plugin is remote
 }
 
 type ServerlessRuntimeType string
@@ -25,12 +25,11 @@ const (
 
 type ServerlessRuntime struct {
 	Model
-	PluginUniqueIdentifier string                            `json:"plugin_unique_identifier" gorm:"size:255;unique"`
-	FunctionURL            string                            `json:"function_url" gorm:"size:255"`
-	FunctionName           string                            `json:"function_name" gorm:"size:127"`
-	Type                   ServerlessRuntimeType             `json:"type" gorm:"size:127"`
-	Declaration            plugin_entities.PluginDeclaration `json:"declaration" gorm:"serializer:json;type:text;size:65535"`
-	Checksum               string                            `json:"checksum" gorm:"size:127;index"`
+	PluginUniqueIdentifier string                `json:"plugin_unique_identifier" gorm:"size:255;unique"`
+	FunctionURL            string                `json:"function_url" gorm:"size:255"`
+	FunctionName           string                `json:"function_name" gorm:"size:127"`
+	Type                   ServerlessRuntimeType `json:"type" gorm:"size:127"`
+	Checksum               string                `json:"checksum" gorm:"size:127;index"`
 }
 
 type PluginDeclaration struct {

+ 4 - 7
internal/types/models/tool.go

@@ -1,12 +1,9 @@
 package models
 
-import "github.com/langgenius/dify-plugin-daemon/pkg/entities/plugin_entities"
-
 type ToolInstallation struct {
 	Model
-	TenantID               string                                  `json:"tenant_id" gorm:"column:tenant_id;type:uuid;index;not null"`
-	Provider               string                                  `json:"provider" gorm:"column:provider;size:127;index;not null"`
-	PluginUniqueIdentifier string                                  `json:"plugin_unique_identifier" gorm:"index;size:255"`
-	PluginID               string                                  `json:"plugin_id" gorm:"index;size:255"`
-	Declaration            plugin_entities.ToolProviderDeclaration `json:"declaration" gorm:"serializer:json;type:text;size:65535;not null"`
+	TenantID               string `json:"tenant_id" gorm:"column:tenant_id;type:uuid;index;not null"`
+	Provider               string `json:"provider" gorm:"column:provider;size:127;index;not null"`
+	PluginUniqueIdentifier string `json:"plugin_unique_identifier" gorm:"index;size:255"`
+	PluginID               string `json:"plugin_id" gorm:"index;size:255"`
 }

+ 184 - 0
internal/utils/cache/helper/combined.go

@@ -0,0 +1,184 @@
+package helper
+
+import (
+	"errors"
+	"strings"
+	"sync"
+	"time"
+
+	"github.com/langgenius/dify-plugin-daemon/internal/db"
+	"github.com/langgenius/dify-plugin-daemon/internal/types/models"
+	"github.com/langgenius/dify-plugin-daemon/internal/utils/cache"
+	"github.com/langgenius/dify-plugin-daemon/pkg/entities/plugin_entities"
+)
+
+var (
+	ErrPluginNotFound = errors.New("plugin not found")
+)
+
+type memCacheItem struct {
+	declaration *plugin_entities.PluginDeclaration
+	accessCount int64
+	lastAccess  time.Time
+}
+
+type memCache struct {
+	sync.RWMutex
+	items    map[string]*memCacheItem
+	itemSize int64
+}
+
+var (
+	// 500MB memory cache
+	maxMemCacheSize = int64(1024)
+	// 600s TTL
+	maxTTL = 600 * time.Second
+
+	pluginCache = &memCache{
+		items:    make(map[string]*memCacheItem),
+		itemSize: 0,
+	}
+)
+
+func (c *memCache) get(key string) *plugin_entities.PluginDeclaration {
+	c.RLock()
+	item, exists := c.items[key]
+	c.RUnlock()
+
+	if !exists {
+		return nil
+	}
+
+	// Check TTL with a read lock first
+	if time.Since(item.lastAccess) > maxTTL {
+		c.Lock()
+		// Double check after acquiring write lock
+		if item, exists = c.items[key]; exists {
+			if time.Since(item.lastAccess) > maxTTL {
+				c.itemSize--
+				delete(c.items, key)
+			}
+		}
+		c.Unlock()
+		return nil
+	}
+
+	// Update access count and time atomically
+	c.Lock()
+	if item, exists = c.items[key]; exists {
+		item.accessCount++
+		item.lastAccess = time.Now()
+	}
+	c.Unlock()
+
+	if exists {
+		return item.declaration
+	}
+	return nil
+}
+
+func (c *memCache) set(key string, declaration *plugin_entities.PluginDeclaration) {
+	c.Lock()
+	defer c.Unlock()
+
+	// Clean expired items first
+	now := time.Now()
+	for k, v := range c.items {
+		if now.Sub(v.lastAccess) > maxTTL {
+			c.itemSize--
+			delete(c.items, k)
+		}
+	}
+
+	// Remove least accessed items if cache is full
+	for c.itemSize >= maxMemCacheSize {
+		var leastKey string
+		var leastCount int64 = -1
+		var oldestAccess = time.Now()
+
+		for k, v := range c.items {
+			// Prioritize by access count, then by age
+			if leastCount == -1 || v.accessCount < leastCount ||
+				(v.accessCount == leastCount && v.lastAccess.Before(oldestAccess)) {
+				leastCount = v.accessCount
+				oldestAccess = v.lastAccess
+				leastKey = k
+			}
+		}
+
+		if leastKey != "" {
+			c.itemSize--
+			delete(c.items, leastKey)
+		}
+	}
+
+	// Add new item
+	c.items[key] = &memCacheItem{
+		declaration: declaration,
+		accessCount: 1,
+		lastAccess:  now,
+	}
+	c.itemSize++
+}
+
+func CombinedGetPluginDeclaration(
+	pluginUniqueIdentifier plugin_entities.PluginUniqueIdentifier,
+	runtimeType plugin_entities.PluginRuntimeType,
+) (*plugin_entities.PluginDeclaration, error) {
+	cacheKey := strings.Join(
+		[]string{
+			"declaration_cache",
+			string(runtimeType),
+			pluginUniqueIdentifier.String(),
+		},
+		":",
+	)
+
+	// Try memory cache first
+	if declaration := pluginCache.get(cacheKey); declaration != nil {
+		return declaration, nil
+	}
+
+	// Try Redis cache next
+	declaration, err := cache.AutoGetWithGetter(
+		cacheKey,
+		func() (*plugin_entities.PluginDeclaration, error) {
+			if runtimeType != plugin_entities.PLUGIN_RUNTIME_TYPE_REMOTE {
+				declaration, err := db.GetOne[models.PluginDeclaration](
+					db.Equal("plugin_unique_identifier", pluginUniqueIdentifier.String()),
+				)
+				if err == db.ErrDatabaseNotFound {
+					return nil, ErrPluginNotFound
+				}
+
+				if err != nil {
+					return nil, err
+				}
+
+				return &declaration.Declaration, nil
+			} else {
+				// try to fetch the declaration from plugin if it's remote
+				plugin, err := db.GetOne[models.Plugin](
+					db.Equal("plugin_unique_identifier", pluginUniqueIdentifier.String()),
+					db.Equal("install_type", string(plugin_entities.PLUGIN_RUNTIME_TYPE_REMOTE)),
+				)
+				if err == db.ErrDatabaseNotFound {
+					return nil, ErrPluginNotFound
+				}
+
+				if err != nil {
+					return nil, err
+				}
+
+				return &plugin.RemoteDeclaration, nil
+			}
+		},
+	)
+
+	if err == nil {
+		// Store successful result in memory cache
+		pluginCache.set(cacheKey, declaration)
+	}
+
+	return declaration, err
+}

+ 0 - 62
internal/utils/cache/helper/redis.go

@@ -1,62 +0,0 @@
-package helper
-
-import (
-	"errors"
-	"strings"
-
-	"github.com/langgenius/dify-plugin-daemon/internal/db"
-	"github.com/langgenius/dify-plugin-daemon/internal/types/models"
-	"github.com/langgenius/dify-plugin-daemon/internal/utils/cache"
-	"github.com/langgenius/dify-plugin-daemon/pkg/entities/plugin_entities"
-)
-
-var (
-	ErrPluginNotFound = errors.New("plugin not found")
-)
-
-func CombinedGetPluginDeclaration(
-	pluginUniqueIdentifier plugin_entities.PluginUniqueIdentifier,
-	tenantId string,
-	runtimeType plugin_entities.PluginRuntimeType,
-) (*plugin_entities.PluginDeclaration, error) {
-	return cache.AutoGetWithGetter(
-		strings.Join(
-			[]string{
-				string(runtimeType),
-				pluginUniqueIdentifier.String(),
-			},
-			":",
-		),
-		func() (*plugin_entities.PluginDeclaration, error) {
-			if runtimeType != plugin_entities.PLUGIN_RUNTIME_TYPE_REMOTE {
-				declaration, err := db.GetOne[models.PluginDeclaration](
-					db.Equal("plugin_unique_identifier", pluginUniqueIdentifier.String()),
-				)
-				if err == db.ErrDatabaseNotFound {
-					return nil, ErrPluginNotFound
-				}
-
-				if err != nil {
-					return nil, err
-				}
-
-				return &declaration.Declaration, nil
-			} else {
-				// try to fetch the declaration from plugin if it's remote
-				plugin, err := db.GetOne[models.Plugin](
-					db.Equal("plugin_unique_identifier", pluginUniqueIdentifier.String()),
-					db.Equal("install_type", string(plugin_entities.PLUGIN_RUNTIME_TYPE_REMOTE)),
-				)
-				if err == db.ErrDatabaseNotFound {
-					return nil, ErrPluginNotFound
-				}
-
-				if err != nil {
-					return nil, err
-				}
-
-				return &plugin.Declaration, nil
-			}
-		},
-	)
-}

+ 5 - 1
internal/utils/cache/redis.go

@@ -72,7 +72,11 @@ func Store(key string, value any, time time.Duration, context ...redis.Cmdable)
 	}
 
 	if _, ok := value.(string); !ok {
-		value = parser.MarshalJson(value)
+		var err error
+		value, err = parser.MarshalCBOR(value)
+		if err != nil {
+			return err
+		}
 	}
 
 	return getCmdable(context...).Set(ctx, serialKey(key), value, time).Err()

+ 8 - 3
internal/utils/cache/redis_auto_type.go

@@ -21,7 +21,12 @@ func AutoSet[T any](key string, value T, context ...redis.Cmdable) error {
 	fullTypeName := pkgPath + "." + typeName
 
 	key = serialKey("auto_type", fullTypeName, key)
-	return getCmdable(context...).Set(ctx, key, parser.MarshalJson(value), time.Minute*30).Err()
+	cborValue, err := parser.MarshalCBOR(value)
+	if err != nil {
+		return err
+	}
+
+	return getCmdable(context...).Set(ctx, key, cborValue, time.Minute*30).Err()
 }
 
 // Get the value with key
@@ -46,7 +51,7 @@ func AutoGetWithGetter[T any](key string, getter func() (*T, error), context ...
 	fullTypeName := pkgPath + "." + typeName
 
 	key = serialKey("auto_type", fullTypeName, key)
-	val, err := getCmdable(context...).Get(ctx, key).Result()
+	val, err := getCmdable(context...).Get(ctx, key).Bytes()
 	if err != nil {
 		if err == redis.Nil {
 			value, err := getter()
@@ -62,7 +67,7 @@ func AutoGetWithGetter[T any](key string, getter func() (*T, error), context ...
 		return nil, err
 	}
 
-	result, err := parser.UnmarshalJson[T](val)
+	result, err := parser.UnmarshalCBOR[T](val)
 	return &result, err
 }
 

+ 13 - 0
internal/utils/parser/cbor.go

@@ -0,0 +1,13 @@
+package parser
+
+import "github.com/fxamacker/cbor/v2"
+
+func MarshalCBOR[T any](v T) ([]byte, error) {
+	return cbor.Marshal(v)
+}
+
+func UnmarshalCBOR[T any](data []byte) (T, error) {
+	var v T
+	err := cbor.Unmarshal(data, &v)
+	return v, err
+}

+ 24 - 0
internal/utils/parser/gob.go

@@ -0,0 +1,24 @@
+package parser
+
+import (
+	"bytes"
+	"encoding/gob"
+)
+
+func MarshalGob(v any) ([]byte, error) {
+	var buf bytes.Buffer
+	enc := gob.NewEncoder(&buf)
+	if err := enc.Encode(v); err != nil {
+		return nil, err
+	}
+	return buf.Bytes(), nil
+}
+
+func UnmarshalGob[T any](data []byte) (T, error) {
+	var v T
+	dec := gob.NewDecoder(bytes.NewReader(data))
+	if err := dec.Decode(&v); err != nil {
+		return v, err
+	}
+	return v, nil
+}

+ 283 - 0
tests/benchmark/encoding/gob_json_test.go

@@ -0,0 +1,283 @@
+package encoding
+
+import (
+	"bytes"
+	"encoding/gob"
+	"encoding/json"
+	"testing"
+	"time"
+
+	"github.com/fxamacker/cbor/v2"
+	"github.com/langgenius/dify-plugin-daemon/internal/utils/parser"
+	"github.com/langgenius/dify-plugin-daemon/pkg/entities/constants"
+	"github.com/langgenius/dify-plugin-daemon/pkg/entities/manifest_entities"
+	"github.com/langgenius/dify-plugin-daemon/pkg/entities/plugin_entities"
+	"github.com/langgenius/dify-plugin-daemon/tests"
+	"github.com/vmihailenco/msgpack/v5"
+)
+
+func BenchmarkMsgpackVsJson(b *testing.B) {
+	declaration := plugin_entities.PluginDeclaration{
+		PluginDeclarationWithoutAdvancedFields: plugin_entities.PluginDeclarationWithoutAdvancedFields{
+			Version: "0.0.1",
+			Type:    manifest_entities.PluginType,
+			Description: plugin_entities.I18nObject{
+				EnUS: "test",
+			},
+			Name: "test",
+			Icon: "test.svg",
+			Label: plugin_entities.I18nObject{
+				EnUS: "test",
+			},
+			Author:    "test",
+			CreatedAt: time.Now(),
+			Resource: plugin_entities.PluginResourceRequirement{
+				Memory: 1,
+				Permission: &plugin_entities.PluginPermissionRequirement{
+					Tool: &plugin_entities.PluginPermissionToolRequirement{
+						Enabled: true,
+					},
+					Model: &plugin_entities.PluginPermissionModelRequirement{
+						Enabled: true,
+					},
+					Node: &plugin_entities.PluginPermissionNodeRequirement{
+						Enabled: true,
+					},
+					Storage: &plugin_entities.PluginPermissionStorageRequirement{
+						Enabled: true,
+						Size:    1024,
+					},
+				},
+			},
+			Plugins: plugin_entities.PluginExtensions{},
+			Meta: plugin_entities.PluginMeta{
+				Version: "0.0.1",
+				Arch: []constants.Arch{
+					constants.AMD64,
+				},
+				Runner: plugin_entities.PluginRunner{
+					Language:   constants.Python,
+					Version:    "3.12",
+					Entrypoint: "main",
+				},
+			},
+		},
+		Model: &plugin_entities.ModelProviderDeclaration{
+			Provider: "test",
+			Label: plugin_entities.I18nObject{
+				EnUS: "test",
+			},
+			Description: &plugin_entities.I18nObject{
+				EnUS: "test",
+			},
+			IconSmall: &plugin_entities.I18nObject{
+				EnUS: "test",
+			},
+			IconLarge: &plugin_entities.I18nObject{
+				EnUS: "test",
+			},
+			ProviderCredentialSchema: &plugin_entities.ModelProviderCredentialSchema{
+				CredentialFormSchemas: []plugin_entities.ModelProviderCredentialFormSchema{
+					{
+						Variable: "test",
+						Label: plugin_entities.I18nObject{
+							EnUS: "test",
+						},
+					},
+				},
+			},
+			Models: []plugin_entities.ModelDeclaration{},
+		},
+	}
+
+	// add 100 models to the declaration
+	for i := 0; i < 100; i++ {
+		declaration.Model.Models = append(declaration.Model.Models, plugin_entities.ModelDeclaration{
+			Model: "test",
+			Label: plugin_entities.I18nObject{
+				EnUS: "test",
+			},
+			ModelProperties: map[string]any{
+				"test": "test",
+			},
+			ParameterRules: []plugin_entities.ModelParameterRule{
+				{
+					Name: "test",
+					Label: &plugin_entities.I18nObject{
+						EnUS: "test",
+					},
+					Type:     parser.ToPtr(plugin_entities.PARAMETER_TYPE_BOOLEAN),
+					Required: true,
+					Help: &plugin_entities.I18nObject{
+						EnUS: "test",
+					},
+				},
+				{
+					Name: "test1",
+					Label: &plugin_entities.I18nObject{
+						EnUS: "test",
+					},
+					Type:     parser.ToPtr(plugin_entities.PARAMETER_TYPE_BOOLEAN),
+					Required: true,
+					Help: &plugin_entities.I18nObject{
+						EnUS: "test",
+					},
+				},
+				{
+					Name: "test2",
+					Label: &plugin_entities.I18nObject{
+						EnUS: "test",
+					},
+					Type:     parser.ToPtr(plugin_entities.PARAMETER_TYPE_BOOLEAN),
+					Required: true,
+					Help: &plugin_entities.I18nObject{
+						EnUS: "test",
+					},
+				},
+				{
+					Name: "test3",
+					Label: &plugin_entities.I18nObject{
+						EnUS: "test",
+					},
+					Type:     parser.ToPtr(plugin_entities.PARAMETER_TYPE_BOOLEAN),
+					Required: true,
+					Help: &plugin_entities.I18nObject{
+						EnUS: "test",
+					},
+				},
+			},
+		})
+	}
+
+	var msgpackBytes []byte
+	var jsonBytes []byte
+	var cborBytes []byte
+	var gobBytes []byte
+	totalBytes := 0
+
+	// Encode benchmarks
+	b.Run("Msgpack Encode", func(b *testing.B) {
+		for i := 0; i < b.N; i++ {
+			var err error
+			msgpackBytes, err = msgpack.Marshal(declaration)
+			if err != nil {
+				b.Fatal(err)
+			}
+			totalBytes += len(msgpackBytes)
+		}
+	})
+	b.Log("Msgpack encoded size:", tests.ReadableBytes(len(msgpackBytes)))
+	b.Log("Total bytes encoded with Msgpack:", tests.ReadableBytes(totalBytes))
+
+	totalBytes = 0
+	b.Run("Json Encode", func(b *testing.B) {
+		for i := 0; i < b.N; i++ {
+			var err error
+			jsonBytes, err = json.Marshal(declaration)
+			if err != nil {
+				b.Fatal(err)
+			}
+			totalBytes += len(jsonBytes)
+		}
+	})
+	b.Log("Json encoded size:", tests.ReadableBytes(len(jsonBytes)))
+	b.Log("Total bytes encoded with Json:", tests.ReadableBytes(totalBytes))
+
+	totalBytes = 0
+	b.Run("CBOR Encode", func(b *testing.B) {
+		for i := 0; i < b.N; i++ {
+			var err error
+			cborBytes, err = cbor.Marshal(declaration)
+			if err != nil {
+				b.Fatal(err)
+			}
+			totalBytes += len(cborBytes)
+		}
+	})
+	b.Log("CBOR encoded size:", tests.ReadableBytes(len(cborBytes)))
+	b.Log("Total bytes encoded with CBOR:", tests.ReadableBytes(totalBytes))
+
+	totalBytes = 0
+	b.Run("GOB Encode", func(b *testing.B) {
+		for i := 0; i < b.N; i++ {
+			var err error
+			var buffer bytes.Buffer
+			enc := gob.NewEncoder(&buffer)
+			err = enc.Encode(declaration)
+			if err != nil {
+				b.Fatal(err)
+			}
+			gobBytes = buffer.Bytes()
+			totalBytes += len(gobBytes)
+		}
+	})
+	b.Log("GOB encoded size:", tests.ReadableBytes(len(gobBytes)))
+	b.Log("Total bytes encoded with GOB:", tests.ReadableBytes(totalBytes))
+
+	// Decode benchmarks
+	totalBytes = 0
+	b.Run("Msgpack Decode", func(b *testing.B) {
+		for i := 0; i < b.N; i++ {
+			err := msgpack.Unmarshal(msgpackBytes, &declaration)
+			if err != nil {
+				b.Fatal(err)
+			}
+			totalBytes += len(msgpackBytes)
+		}
+	})
+	b.Log("Total bytes decoded with Msgpack:", tests.ReadableBytes(totalBytes))
+
+	totalBytes = 0
+	b.Run("Json Decode", func(b *testing.B) {
+		for i := 0; i < b.N; i++ {
+			var err error
+			var decodedDeclaration plugin_entities.PluginDeclaration
+			err = json.Unmarshal(jsonBytes, &decodedDeclaration)
+			if err != nil {
+				b.Fatal(err)
+			}
+			totalBytes += len(jsonBytes)
+		}
+	})
+	b.Log("Total bytes decoded with Json:", tests.ReadableBytes(totalBytes))
+
+	totalBytes = 0
+	b.Run("CBOR Decode", func(b *testing.B) {
+		for i := 0; i < b.N; i++ {
+			var decodedDeclaration plugin_entities.PluginDeclaration
+			err := cbor.Unmarshal(cborBytes, &decodedDeclaration)
+			if err != nil {
+				b.Fatal(err)
+			}
+			totalBytes += len(cborBytes)
+		}
+	})
+	b.Log("Total bytes decoded with CBOR:", tests.ReadableBytes(totalBytes))
+
+	totalBytes = 0
+	b.Run("GOB Decode", func(b *testing.B) {
+		for i := 0; i < b.N; i++ {
+			var decodedDeclaration plugin_entities.PluginDeclaration
+			dec := gob.NewDecoder(bytes.NewBuffer(gobBytes))
+			err := dec.Decode(&decodedDeclaration)
+			if err != nil {
+				b.Fatal(err)
+			}
+			totalBytes += len(gobBytes)
+		}
+	})
+	b.Log("Total bytes decoded with GOB:", tests.ReadableBytes(totalBytes))
+
+	totalBytes = 0
+	b.Run("Map Json Decode", func(b *testing.B) {
+		for i := 0; i < b.N; i++ {
+			var decoded map[string]any
+			err := json.Unmarshal(jsonBytes, &decoded)
+			if err != nil {
+				b.Fatal(err)
+			}
+			totalBytes += len(jsonBytes)
+		}
+	})
+	b.Log("Total map bytes decoded with Json:", tests.ReadableBytes(totalBytes))
+}