feat[0.4.0]: add dynamic select support (#163)

* feat: add dynamic select support

- Introduced ParameterOption class for parameter options with value, label, and optional icon.
- Updated ToolParameterOption to inherit from ParameterOption.
- Added DYNAMIC_SELECT to CommonParameterType enum.
- Implemented fetch_parameter_options method in Tool class for fetching parameter options.
- Created DynamicSelectProtocol for dynamic select functionality.
- Added tests for Tool construction and parameter options fetching.

* feat: implement dynamic parameter fetching functionality

- Added DynamicParameterFetchParameterOptionsRequest class for dynamic parameter requests.
- Introduced DynamicParameterActions enum for action types related to dynamic parameters.
- Enhanced PluginExecutor with methods to handle dynamic parameter fetching.
- Updated Tool interface to include a method for fetching parameter options.
- Documented the DynamicSelectProtocol for clarity on its usage.

* feat: enhance plugin functionality with dynamic parameter options and trigger interface

- Added dynamic parameter fetching capabilities to the Plugin class.
- Introduced TriggerProvider and Trigger classes for managing trigger functionalities.
- Updated Tool interface to enforce implementation of credential validation and OAuth methods.
- Enhanced error messages for NotImplementedError in ToolProvider and Trigger classes.
- Removed deprecated tools and their configurations from the codebase.

* docs: update README.md to include support for `dynamic-select` parameter type in manifest versioning

* chore: remove code_based_workflow
This commit is contained in:
Yeuoly
2025-06-27 15:59:22 +08:00
committed by GitHub
parent 3babba0c65
commit 132d6572ee
41 changed files with 290 additions and 543 deletions
-4
View File
@@ -1,4 +0,0 @@
INSTALL_METHOD=remote
REMOTE_INSTALL_HOST=localhost
REMOTE_INSTALL_PORT=5003
REMOTE_INSTALL_KEY=23620d39-d006-4613-85be-844874ed5d89
@@ -1 +0,0 @@
.env
@@ -1,10 +0,0 @@
<svg width="80" height="80" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Layer 1</title>
<path d="m19.54023,25.86207c0,-0.22989 -0.06147,-0.93416 0.45977,-2.9885c0.41159,-1.62219 0.4842,-1.97537 1.6092,-3.44828c0.19734,-0.25836 0.45977,-0.22989 0.45977,-0.22989c0,0 0.25366,-0.02153 0.45977,0.22989c0.52549,0.641 1.54632,1.21692 2.52873,2.06897c0.86834,0.75311 2.29885,1.83908 2.98851,2.52874c0.91954,0.91954 1.6092,1.60919 2.29885,2.52873l0.22989,0.22989l0.22989,0.22989l0,0" id="svg_1" stroke="#000" fill="none"/>
<path d="m44.82759,25.17241c0,0 -0.04347,-0.23403 0,-0.45977c0.23411,-1.21563 1.45889,-2.00125 1.83908,-2.52873c0.30056,-0.41701 0.68966,-0.68966 0.68966,-0.68966c0,0 0.06733,-0.16255 0.22989,0c0.16255,0.16255 0.51332,0.59534 1.37931,1.14943c1.2399,0.79333 2.86973,2.18008 4.5977,3.90804c1.72797,1.72796 2.52874,2.75862 3.44828,3.67816c0.45977,0.45977 0.45977,0.68966 0.68966,0.68966l0,0.22989" id="svg_2" stroke="#000" fill="none"/>
<path d="m31.72414,48.85057c0,0 0,0.22989 0,0.22989c0,0.68966 0.37026,1.41593 0.68965,2.06897c0.36416,0.74458 0.61898,1.19218 0.91954,1.6092c0.19009,0.26374 0.68966,0.91954 1.14943,1.14943c0.45977,0.22989 0.9623,0.15921 1.37931,0.45977c0.26374,0.19009 0.47727,0.31786 0.68966,0.22989c0.30036,-0.12441 0.74316,-0.85822 2.06897,-2.06897c1.68046,-1.53462 4.24034,-3.32138 5.97701,-4.82759c1.47362,-1.27806 2.29885,-2.06897 2.75862,-2.29885l0,0" id="svg_3" stroke="#000" fill="none"/>
<polyline stroke-linecap="round" id="svg_4" points="158.85057471264366,-8.850574712643677 158.85057471264366,-8.850574712643677 " stroke="#000" fill="none"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

@@ -1,6 +0,0 @@
from dify_plugin import DifyPluginEnv, Plugin
plugin = Plugin(DifyPluginEnv(MAX_REQUEST_TIMEOUT=30))
if __name__ == "__main__":
plugin.run()
@@ -1,41 +0,0 @@
version: 0.0.1
type: plugin
author: "langgenius"
name: "code_based_workflow"
label:
en_US: "code_based_workflow"
description:
en_US: A workflow for performing a code-based workflow.
zh_Hans: 一个用于执行代码工作流的工具。
created_at: "2024-07-12T08:03:44.658609186Z"
icon: icon.svg
resource:
memory: 1048576
permission:
tool:
enabled: true
model:
enabled: true
llm: true
rerank: true
moderation: true
tts: true
speech2text: true
text_embedding: true
storage:
enabled: true
size: 1048576
node:
enabled: true
plugins:
tools:
- "provider/code_based_workflow.yaml"
meta:
version: 0.0.1
arch:
- "amd64"
- "arm64"
runner:
language: "python"
version: "3.12"
entrypoint: "main"
@@ -1,8 +0,0 @@
from typing import Any
from dify_plugin import ToolProvider
class CodeBasedWorkflowProvider(ToolProvider):
def _validate_credentials(self, credentials: dict[str, Any]) -> None:
pass
@@ -1,28 +0,0 @@
identity:
author: Dify
name: code_based_workflow
label:
en_US: CodeBasedWorkflow
zh_Hans: CodeBasedWorkflow
pt_BR: CodeBasedWorkflow
description:
en_US: CodeBasedWorkflow
zh_Hans: CodeBasedWorkflow
pt_BR: CodeBasedWorkflow
icon: icon.svg
tags:
- search
tools:
- tools/parameter_extractor.yaml
- tools/question_classifier.yaml
- tools/llm.yaml
- tools/tool.yaml
- tools/moderation.yaml
- tools/rerank.yaml
- tools/tts.yaml
- tools/upload_file.yaml
- tools/summary.yaml
- tools/transform_image.yaml
extra:
python:
source: provider/code_based_workflow.py
@@ -1 +0,0 @@
dify_plugin
@@ -1,29 +0,0 @@
from collections.abc import Generator
from typing import Any
from dify_plugin import Tool
from dify_plugin.entities.model.llm import LLMModelConfig
from dify_plugin.entities.model.message import SystemPromptMessage, UserPromptMessage
from dify_plugin.entities.tool import ToolInvokeMessage
class LLMTool(Tool):
def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:
response = self.session.model.llm.invoke(
model_config=LLMModelConfig(
provider="openai",
model="gpt-4o-mini",
mode="chat",
completion_params={},
),
prompt_messages=[
SystemPromptMessage(content="you are a helpful assistant"),
UserPromptMessage(content=tool_parameters.get("query")),
],
stream=True,
)
for chunk in response:
if chunk.delta.message:
assert isinstance(chunk.delta.message.content, str)
yield self.create_text_message(text=chunk.delta.message.content)
@@ -1,30 +0,0 @@
identity:
name: llm
author: Dify
label:
en_US: LLM
zh_Hans: LLM
pt_BR: LLM
description:
human:
en_US: A tool for invoking a large language model
zh_Hans: 用于调用大型语言模型的工具
pt_BR: A tool for invoking a large language model
llm: A tool for invoking a large language model
parameters:
- name: prompt
type: string
required: true
label:
en_US: Prompt string
zh_Hans: 提示字符串
pt_BR: Prompt string
human_description:
en_US: used for searching
zh_Hans: 用于搜索网页内容
pt_BR: used for searching
llm_description: key words for searching
form: llm
extra:
python:
source: tools/llm.py
@@ -1,22 +0,0 @@
from collections.abc import Generator
from dify_plugin.entities.model.moderation import ModerationModelConfig
from dify_plugin.entities.tool import ToolInvokeMessage
from dify_plugin.interfaces.tool import Tool
class Moderation(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
response = self.session.model.moderation.invoke(
model_config=ModerationModelConfig(
provider="openai",
model="text-moderation-stable",
),
text=tool_parameters["text"],
)
yield self.create_json_message(
{
"data": response,
}
)
@@ -1,30 +0,0 @@
identity:
name: moderation
author: Dify
label:
en_US: Moderation
zh_Hans: 内容审核
pt_BR: Moderation
description:
human:
en_US: A tool for moderation
zh_Hans: 用于内容审核的工具
pt_BR: A tool for moderation
llm: A tool for moderation
parameters:
- name: text
type: string
required: true
label:
en_US: Text to moderate
zh_Hans: 要审核的文本
pt_BR: Text to moderate
human_description:
en_US: Text to moderate
zh_Hans: 要审核的文本
pt_BR: Text to moderate
llm_description: Text to moderate
form: llm
extra:
python:
source: tools/moderation.py
@@ -1,28 +0,0 @@
from collections.abc import Generator
from dify_plugin import Tool
from dify_plugin.entities.tool import ToolInvokeMessage
from dify_plugin.entities.workflow_node import ModelConfig, ParameterConfig
class ParameterExtractorTool(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
response = self.session.workflow_node.parameter_extractor.invoke(
parameters=[
ParameterConfig(
name="name",
description="name of the person",
required=True,
type="string",
)
],
model=ModelConfig(
provider="openai",
name="gpt-4o-mini",
completion_params={},
),
query="My name is John Doe",
instruction="Extract the name of the person",
)
yield self.create_json_message(response.outputs)
@@ -1,30 +0,0 @@
identity:
name: parameter_extractor
author: Dify
label:
en_US: Parameter Extractor
zh_Hans: 参数提取器
pt_BR: Parameter Extractor
description:
human:
en_US: A tool for extracting parameters from a given string
zh_Hans: 从给定字符串中提取参数的工具
pt_BR: A tool for extracting parameters from a given string
llm: A tool for extracting parameters from a given string
parameters:
- name: prompt
type: string
required: true
label:
en_US: Prompt string
zh_Hans: 提示字符串
pt_BR: Prompt string
human_description:
en_US: used for extracting parameters
zh_Hans: 用于提取参数
pt_BR: used for extracting parameters
llm_description: key words for extracting parameters
form: llm
extra:
python:
source: tools/parameter_extractor.py
@@ -1,9 +0,0 @@
from collections.abc import Generator
from dify_plugin import Tool
from dify_plugin.entities.tool import ToolInvokeMessage
class QuestionClassifierTool(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
return super()._invoke(tool_parameters)
@@ -1,30 +0,0 @@
identity:
name: question_classifier
author: Dify
label:
en_US: Question Classifier
zh_Hans: 问题分类器
pt_BR: Question Classifier
description:
human:
en_US: A tool for classifying questions
zh_Hans: 用于分类问题的工具
pt_BR: A tool for classifying questions
llm: A tool for classifying questions
parameters:
- name: prompt
type: string
required: true
label:
en_US: Prompt string
zh_Hans: 提示字符串
pt_BR: Prompt string
human_description:
en_US: used for classifying questions
zh_Hans: 用于分类问题
pt_BR: used for classifying questions
llm_description: key words for classifying questions
form: llm
extra:
python:
source: tools/question_classifier.py
@@ -1,25 +0,0 @@
from collections.abc import Generator
from dify_plugin.entities.model.rerank import RerankModelConfig
from dify_plugin.entities.tool import ToolInvokeMessage
from dify_plugin.interfaces.tool import Tool
class Rerank(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
response = self.session.model.rerank.invoke(
model_config=RerankModelConfig(
provider="jina",
model="jina-embeddings-v2-base-v1.0",
score_threshold=0.5,
top_n=10,
),
docs=["Kasumi", "Utae", "Arisa"],
query="Utae",
)
yield self.create_json_message(
{
"data": response.docs,
}
)
@@ -1,17 +0,0 @@
identity:
name: rerank
author: Dify
label:
en_US: Rerank
zh_Hans: 重新排序
pt_BR: Rerank
description:
human:
en_US: A tool for reranking questions
zh_Hans: 用于重新排序问题的工具
pt_BR: A tool for reranking questions
llm: A tool for reranking questions
parameters:
extra:
python:
source: tools/rerank.py
@@ -1,19 +0,0 @@
from collections.abc import Generator
from dify_plugin.entities.tool import ToolInvokeMessage
from dify_plugin.interfaces.tool import Tool
class Summary(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
response = self.session.model.summary.invoke(
text="Hello, world!",
instruction="Summarize the text",
min_summarize_length=1,
)
yield self.create_json_message(
{
"data": response,
}
)
@@ -1,17 +0,0 @@
identity:
name: summary
author: Dify
label:
en_US: Summary
zh_Hans: 总结
pt_BR: Summary
description:
human:
en_US: A tool for summarizing questions
zh_Hans: 用于总结问题的工具
pt_BR: A tool for summarizing questions
llm: A tool for reranking questions
parameters:
extra:
python:
source: tools/summary.py
@@ -1,9 +0,0 @@
from collections.abc import Generator
from dify_plugin import Tool
from dify_plugin.entities.tool import ToolInvokeMessage
class ToolTool(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
yield self.create_image_message("https://assets.dify.ai/images/dify_logo_dark_s.png")
@@ -1,16 +0,0 @@
identity:
name: tool
author: Dify
label:
en_US: Tool
zh_Hans: 工具
pt_BR: Tool
description:
human:
en_US: invoke other tools
zh_Hans: 调用其他工具
pt_BR: invoke other tools
llm: invoke other tools
extra:
python:
source: tools/tool.py
@@ -1,19 +0,0 @@
from collections.abc import Generator
from dify_plugin import Tool
from dify_plugin.entities.tool import ToolInvokeMessage
from dify_plugin.file.file import File
class TransformImageTool(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
for image in tool_parameters["image"]:
assert isinstance(image, File)
yield self.create_json_message(
{
"mime_type": image.mime_type,
"type": image.type,
"length": len(image.blob),
}
)
yield self.create_blob_message(image.blob, {"mime_type": image.mime_type})
@@ -1,30 +0,0 @@
identity:
name: transform_image
author: Dify
label:
en_US: Transform Image
zh_Hans: 转换图片
pt_BR: Transformar Imagem
description:
human:
en_US: Transform image to another format
zh_Hans: 将图片转换为另一种格式
pt_BR: Transformar imagem para outro formato
llm: Transform image to another format
parameters:
- name: image
type: files
required: true
label:
en_US: Images
zh_Hans: 图片
pt_BR: Imagens
human_description:
en_US: Images to transform
zh_Hans: 需要转换的图片
pt_BR: Imagens para transformar
llm_description: Images to transform
form: llm
extra:
python:
source: tools/transform_image.py
@@ -1,21 +0,0 @@
import binascii
from collections.abc import Generator
from dify_plugin.entities.model.tts import TTSModelConfig
from dify_plugin.entities.tool import ToolInvokeMessage
from dify_plugin.interfaces.tool import Tool
class TTS(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
response = self.session.model.tts.invoke(
model_config=TTSModelConfig(
provider="openai",
model="tts-1",
voice="alloy",
),
content_text="Hello, world!",
)
for chunk in response:
yield self.create_text_message(binascii.hexlify(chunk).decode())
@@ -1,17 +0,0 @@
identity:
name: tts
author: Dify
label:
en_US: TTS
zh_Hans: 文本转语音
pt_BR: TTS
description:
human:
en_US: A tool for text to speech
zh_Hans: 用于文本转语音的工具
pt_BR: A tool for text to speech
llm: A tool for text to speech
parameters:
extra:
python:
source: tools/tts.py
@@ -1,10 +0,0 @@
from collections.abc import Generator
from dify_plugin import Tool
from dify_plugin.entities.tool import ToolInvokeMessage
class UploadFileTool(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
response = self.session.file.upload("1.txt", b"", "text/plain")
yield self.create_text_message(f"file id: {response.id}")
@@ -1,16 +0,0 @@
identity:
name: upload_file
author: Dify
label:
en_US: Upload File
zh_Hans: 上传文件
pt_BR: Upload File
description:
human:
en_US: upload file
zh_Hans: 上传文件
pt_BR: upload file
llm: upload file
extra:
python:
source: tools/upload_file.py