Implementation:Langgenius Dify UpdateFromMarketPlace
| Knowledge Sources | Dify |
|---|---|
| Domains | Plugin_System, Marketplace, Frontend |
| Last Updated | 2026-02-12 00:00 GMT |
Overview
Description
The UpdateFromMarketPlace module in web/service/plugins.ts provides the imperative service functions for installing and upgrading plugins from three distinct sources: the Dify Marketplace, GitHub repositories, and local file uploads. These functions are thin wrappers around HTTP POST requests that return typed responses, serving as the transport layer between the frontend UI and the backend plugin installation pipeline.
The three primary functions are:
- updateFromMarketPlace -- Upgrades a plugin from the marketplace by posting a body containing the original and new plugin unique identifiers.
- uploadGitHub -- Resolves a plugin package from a GitHub repository by specifying the repo URL, version tag, and package name, returning a unique identifier for subsequent installation.
- uploadFile -- Uploads a local
.pkgor.bundlefile asmultipart/form-datausingXMLHttpRequest.
Usage
These functions are called by higher-level React components and hooks when a user initiates a plugin installation or upgrade. They are also consumed by the composite useInstallOrUpdate hook which orchestrates multi-dependency installations.
Code Reference
Source Location
web/service/plugins.ts (Lines 20--55)
Signature
export const updateFromMarketPlace = async (body: Record<string, string>) => {
return post<InstallPackageResponse>('/workspaces/current/plugin/upgrade/marketplace', { body })
}
export const uploadGitHub = async (
repoUrl: string,
selectedVersion: string,
selectedPackage: string,
) => {
return post<uploadGitHubResponse>('/workspaces/current/plugin/upload/github', {
body: { repo: repoUrl, version: selectedVersion, package: selectedPackage },
})
}
export const uploadFile = async (file: File, isBundle: boolean) => {
const formData = new FormData()
formData.append(isBundle ? 'bundle' : 'pkg', file)
return upload(
{ xhr: new XMLHttpRequest(), data: formData },
false,
`/workspaces/current/plugin/upload/${isBundle ? 'bundle' : 'pkg'}`,
)
}
Import
import { updateFromMarketPlace, uploadGitHub, uploadFile } from '@/service/plugins'
I/O Contract
updateFromMarketPlace
| Direction | Field | Type | Description |
|---|---|---|---|
| Input | body | Record<string, string> |
Key-value pairs including original_plugin_unique_identifier and new_plugin_unique_identifier
|
| Output | task_id | string |
The ID of the asynchronous installation task |
| Output | all_installed | boolean |
Whether the installation completed synchronously |
uploadGitHub
| Direction | Field | Type | Description |
|---|---|---|---|
| Input | repoUrl | string |
The GitHub repository URL (e.g., https://github.com/org/repo)
|
| Input | selectedVersion | string |
The release tag or version string |
| Input | selectedPackage | string |
The package name within the release |
| Output | unique_identifier | string |
The resolved plugin unique identifier for subsequent install |
uploadFile
| Direction | Field | Type | Description |
|---|---|---|---|
| Input | file | File |
The local file object (.pkg or .bundle)
|
| Input | isBundle | boolean |
Whether the file is a bundle (multiple plugins) or a single package |
| Output | (varies) | upload response | The upload result containing the resolved package identifier |
Usage Examples
Upgrading a marketplace plugin
import { updateFromMarketPlace } from '@/service/plugins'
const response = await updateFromMarketPlace({
original_plugin_unique_identifier: 'org/plugin@1.0.0',
new_plugin_unique_identifier: 'org/plugin@2.0.0',
})
if (!response.all_installed) {
// Poll for task completion
await pollTaskStatus(response.task_id)
}
Installing from GitHub
import { uploadGitHub } from '@/service/plugins'
const { unique_identifier } = await uploadGitHub(
'https://github.com/langgenius/dify-plugin-example',
'v1.2.0',
'main-package',
)
// Use unique_identifier for the install step
Uploading a local package file
import { uploadFile } from '@/service/plugins'
const fileInput = document.querySelector('input[type="file"]') as HTMLInputElement
const file = fileInput.files![0]
const result = await uploadFile(file, false) // false = single .pkg, not a bundle