dify_plugin 0.3.0__tar.gz → 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/PKG-INFO +1 -2
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/entities/plugin/request.py +28 -6
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/plugin_executor.py +30 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/plugin_registration.py +22 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/tool.py +7 -27
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/integration/run.py +32 -1
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/tool/__init__.py +16 -3
- dify_plugin-0.3.2/dify_plugin/protocol/oauth.py +27 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/pyproject.toml +1 -2
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/__mock_server/openai.py +3 -3
- dify_plugin-0.3.2/tests/consts/mockserver.py +1 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/integration/test_invoke_llm.py +1 -1
- dify_plugin-0.3.2/tests/interfaces/model/openai_compatible/__init__.py +0 -0
- dify_plugin-0.3.2/tests/interfaces/tool/__init__.py +0 -0
- dify_plugin-0.3.2/tests/interfaces/tool/test_construct_tool_provider.py +20 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/LICENSE +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/README.md +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/cli.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/commands/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/commands/generate_docs.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/config/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/config/config.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/config/integration_config.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/config/logger_format.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/documentation/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/documentation/generator.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/documentation/schema_doc.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/entities/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/entities/invocation.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/entities/message.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/entities/plugin/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/entities/plugin/io.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/entities/plugin/parameter_type.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/entities/plugin/setup.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/runtime.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/__base/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/__base/filter_reader.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/__base/request_reader.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/__base/response_writer.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/__base/writer_entities.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/io_server.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/router.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/serverless/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/serverless/request_reader.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/serverless/response_writer.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/stdio/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/stdio/request_reader.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/stdio/response_writer.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/tcp/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/tcp/request_reader.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/utils/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/utils/class_loader.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/utils/http_parser.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/utils/position_helper.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/utils/yaml_loader.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/agent.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/endpoint.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/model/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/model/llm.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/model/message.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/model/moderation.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/model/provider.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/model/rerank.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/model/speech2text.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/model/text_embedding.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/model/tts.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/oauth.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/provider_config.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/entities/workflow_node.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/errors/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/errors/model.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/errors/tool.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/file/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/file/constants.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/file/entities.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/file/file.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/integration/entities.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/integration/exc.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/agent/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/endpoint/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/ai_model.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/audio.mp3 +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/large_language_model.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/moderation_model.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/openai_compatible/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/openai_compatible/common.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/openai_compatible/llm.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/openai_compatible/provider.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/openai_compatible/rerank.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/openai_compatible/speech2text.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/openai_compatible/text_embedding.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/openai_compatible/tts.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/rerank_model.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/speech2text_model.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/text_embedding_model.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/tts_model.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/app/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/app/chat.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/app/completion.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/app/workflow.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/file.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/model/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/model/llm.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/model/moderation.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/model/rerank.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/model/speech2text.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/model/text_embedding.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/model/tts.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/storage.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/tool.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/workflow_node/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/workflow_node/parameter_extractor.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/workflow_node/question_classifier.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/plugin.py +0 -0
- {dify_plugin-0.3.0/dify_plugin/tool → dify_plugin-0.3.2/dify_plugin/protocol}/__init__.py +0 -0
- {dify_plugin-0.3.0/tests → dify_plugin-0.3.2/dify_plugin/tool}/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/tool/entities.py +0 -0
- {dify_plugin-0.3.0/tests/interfaces/model → dify_plugin-0.3.2/tests}/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/__mock_server/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/config/test_config.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/entities/endpoint/test_endpoint_group.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/entities/models/test_llm.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/entities/plugin/test_declaration.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/interfaces/agent/test_agent.py +0 -0
- {dify_plugin-0.3.0/tests/interfaces/model/openai_compatible → dify_plugin-0.3.2/tests/interfaces/model}/__init__.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/interfaces/model/openai_compatible/test_increase_tool_call.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/invocations/test_storage.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/servers/test_stdio.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/test_llm_result.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/test_prompt_message.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/test_tool_call_model_init.py +0 -0
- {dify_plugin-0.3.0 → dify_plugin-0.3.2}/tests/utils/test_http_parser.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dify_plugin
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Dify Plugin SDK
|
|
5
5
|
Keywords: dify,plugin,sdk
|
|
6
6
|
Author-Email: langgenius <hello@dify.ai>
|
|
@@ -14,7 +14,6 @@ Requires-Dist: gevent~=24.11.1
|
|
|
14
14
|
Requires-Dist: httpx~=0.28.1
|
|
15
15
|
Requires-Dist: pydantic_settings<3.0.0,>=2.5.0
|
|
16
16
|
Requires-Dist: pydantic>=2.8.2
|
|
17
|
-
Requires-Dist: pydub~=0.25.1
|
|
18
17
|
Requires-Dist: pyyaml~=6.0.1
|
|
19
18
|
Requires-Dist: requests~=2.32.3
|
|
20
19
|
Requires-Dist: socksio==1.0.0
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Mapping
|
|
2
|
+
from enum import StrEnum
|
|
2
3
|
from typing import Any, Optional
|
|
3
4
|
|
|
4
5
|
from pydantic import BaseModel, ConfigDict, field_validator
|
|
@@ -15,24 +16,25 @@ from dify_plugin.entities.model.message import (
|
|
|
15
16
|
)
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
class PluginInvokeType(
|
|
19
|
+
class PluginInvokeType(StrEnum):
|
|
19
20
|
Tool = "tool"
|
|
20
21
|
Model = "model"
|
|
21
22
|
Endpoint = "endpoint"
|
|
22
23
|
Agent = "agent_strategy"
|
|
24
|
+
OAuth = "oauth"
|
|
23
25
|
|
|
24
26
|
|
|
25
|
-
class AgentActions(
|
|
27
|
+
class AgentActions(StrEnum):
|
|
26
28
|
InvokeAgentStrategy = "invoke_agent_strategy"
|
|
27
29
|
|
|
28
30
|
|
|
29
|
-
class ToolActions(
|
|
31
|
+
class ToolActions(StrEnum):
|
|
30
32
|
ValidateCredentials = "validate_tool_credentials"
|
|
31
33
|
InvokeTool = "invoke_tool"
|
|
32
34
|
GetToolRuntimeParameters = "get_tool_runtime_parameters"
|
|
33
35
|
|
|
34
36
|
|
|
35
|
-
class ModelActions(
|
|
37
|
+
class ModelActions(StrEnum):
|
|
36
38
|
ValidateProviderCredentials = "validate_provider_credentials"
|
|
37
39
|
ValidateModelCredentials = "validate_model_credentials"
|
|
38
40
|
InvokeLLM = "invoke_llm"
|
|
@@ -47,10 +49,15 @@ class ModelActions(Enum):
|
|
|
47
49
|
GetAIModelSchemas = "get_ai_model_schemas"
|
|
48
50
|
|
|
49
51
|
|
|
50
|
-
class EndpointActions(
|
|
52
|
+
class EndpointActions(StrEnum):
|
|
51
53
|
InvokeEndpoint = "invoke_endpoint"
|
|
52
54
|
|
|
53
55
|
|
|
56
|
+
class OAuthActions(StrEnum):
|
|
57
|
+
GetAuthorizationUrl = "get_authorization_url"
|
|
58
|
+
GetCredentials = "get_credentials"
|
|
59
|
+
|
|
60
|
+
|
|
54
61
|
# merge all the access actions
|
|
55
62
|
PluginAccessAction = AgentActions | ToolActions | ModelActions | EndpointActions
|
|
56
63
|
|
|
@@ -227,3 +234,18 @@ class EndpointInvokeRequest(BaseModel):
|
|
|
227
234
|
action: EndpointActions = EndpointActions.InvokeEndpoint
|
|
228
235
|
settings: dict
|
|
229
236
|
raw_http_request: str
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
class OAuthGetAuthorizationUrlRequest(BaseModel):
|
|
240
|
+
type: PluginInvokeType = PluginInvokeType.OAuth
|
|
241
|
+
action: OAuthActions = OAuthActions.GetAuthorizationUrl
|
|
242
|
+
provider: str
|
|
243
|
+
system_credentials: Mapping[str, Any]
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
class OAuthGetCredentialsRequest(BaseModel):
|
|
247
|
+
type: PluginInvokeType = PluginInvokeType.OAuth
|
|
248
|
+
action: OAuthActions = OAuthActions.GetCredentials
|
|
249
|
+
provider: str
|
|
250
|
+
system_credentials: Mapping[str, Any]
|
|
251
|
+
raw_http_request: str
|
|
@@ -20,6 +20,8 @@ from dify_plugin.core.entities.plugin.request import (
|
|
|
20
20
|
ModelInvokeTTSRequest,
|
|
21
21
|
ModelValidateModelCredentialsRequest,
|
|
22
22
|
ModelValidateProviderCredentialsRequest,
|
|
23
|
+
OAuthGetAuthorizationUrlRequest,
|
|
24
|
+
OAuthGetCredentialsRequest,
|
|
23
25
|
ToolGetRuntimeParametersRequest,
|
|
24
26
|
ToolInvokeRequest,
|
|
25
27
|
ToolValidateCredentialsRequest,
|
|
@@ -37,6 +39,8 @@ from dify_plugin.interfaces.model.rerank_model import RerankModel
|
|
|
37
39
|
from dify_plugin.interfaces.model.speech2text_model import Speech2TextModel
|
|
38
40
|
from dify_plugin.interfaces.model.text_embedding_model import TextEmbeddingModel
|
|
39
41
|
from dify_plugin.interfaces.model.tts_model import TTSModel
|
|
42
|
+
from dify_plugin.interfaces.tool import ToolProvider
|
|
43
|
+
from dify_plugin.protocol.oauth import OAuthProviderProtocol
|
|
40
44
|
|
|
41
45
|
|
|
42
46
|
class PluginExecutor:
|
|
@@ -321,3 +325,29 @@ class PluginExecutor:
|
|
|
321
325
|
result["result"] += binascii.hexlify(chunk.encode("utf-8")).decode()
|
|
322
326
|
|
|
323
327
|
yield result
|
|
328
|
+
|
|
329
|
+
def _get_oauth_provider_instance(self, provider: str) -> OAuthProviderProtocol:
|
|
330
|
+
provider_cls = self.registration.get_supported_oauth_provider_cls(provider)
|
|
331
|
+
if provider_cls is None:
|
|
332
|
+
raise ValueError(f"Provider `{provider}` does not support OAuth")
|
|
333
|
+
|
|
334
|
+
if provider_cls == ToolProvider:
|
|
335
|
+
return provider_cls()
|
|
336
|
+
|
|
337
|
+
raise ValueError(f"Provider `{provider}` does not support OAuth")
|
|
338
|
+
|
|
339
|
+
def get_oauth_authorization_url(self, session: Session, data: OAuthGetAuthorizationUrlRequest):
|
|
340
|
+
provider_instance = self._get_oauth_provider_instance(data.provider)
|
|
341
|
+
|
|
342
|
+
return {
|
|
343
|
+
"authorization_url": provider_instance.oauth_get_authorization_url(data.system_credentials),
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
def get_oauth_credentials(self, session: Session, data: OAuthGetCredentialsRequest):
|
|
347
|
+
provider_instance = self._get_oauth_provider_instance(data.provider)
|
|
348
|
+
bytes_data = binascii.unhexlify(data.raw_http_request)
|
|
349
|
+
request = parse_raw_request(bytes_data)
|
|
350
|
+
|
|
351
|
+
return {
|
|
352
|
+
"credentials": provider_instance.oauth_get_credentials(data.system_credentials, request),
|
|
353
|
+
}
|
|
@@ -28,6 +28,7 @@ from dify_plugin.interfaces.model.speech2text_model import Speech2TextModel
|
|
|
28
28
|
from dify_plugin.interfaces.model.text_embedding_model import TextEmbeddingModel
|
|
29
29
|
from dify_plugin.interfaces.model.tts_model import TTSModel
|
|
30
30
|
from dify_plugin.interfaces.tool import Tool, ToolProvider
|
|
31
|
+
from dify_plugin.protocol.oauth import OAuthProviderProtocol
|
|
31
32
|
|
|
32
33
|
T = TypeVar("T")
|
|
33
34
|
|
|
@@ -63,6 +64,15 @@ class PluginRegistration:
|
|
|
63
64
|
]
|
|
64
65
|
endpoints_configuration: list[EndpointProviderConfiguration]
|
|
65
66
|
endpoints: Map
|
|
67
|
+
datasource_configuration: list[None] # TBD
|
|
68
|
+
datasource_mapping: dict[ # provider -> (provider_cls, datasource_mapping)
|
|
69
|
+
str,
|
|
70
|
+
tuple[
|
|
71
|
+
None,
|
|
72
|
+
dict[str, tuple[None, type[None]]], # datasource_name -> (datasource_configuration, datasource_cls)
|
|
73
|
+
],
|
|
74
|
+
] # TBD
|
|
75
|
+
|
|
66
76
|
files: list[PluginAsset]
|
|
67
77
|
|
|
68
78
|
def __init__(self, config: DifyPluginEnv) -> None:
|
|
@@ -338,6 +348,18 @@ class PluginRegistration:
|
|
|
338
348
|
if registration:
|
|
339
349
|
return registration
|
|
340
350
|
|
|
351
|
+
def get_supported_oauth_provider_cls(self, provider: str) -> type[OAuthProviderProtocol] | None:
|
|
352
|
+
"""
|
|
353
|
+
get provider which supports oauth
|
|
354
|
+
:param provider: provider name
|
|
355
|
+
:return: supported oauth providers
|
|
356
|
+
"""
|
|
357
|
+
for provider_registration in self.tools_mapping:
|
|
358
|
+
if provider_registration == provider and self.tools_mapping[provider_registration][0].oauth_schema:
|
|
359
|
+
return self.tools_mapping[provider_registration][1]
|
|
360
|
+
|
|
361
|
+
return None
|
|
362
|
+
|
|
341
363
|
def dispatch_endpoint_request(self, request: Request) -> tuple[type[Endpoint], Mapping]:
|
|
342
364
|
"""
|
|
343
365
|
dispatch endpoint request, match the request to the registered endpoints
|
|
@@ -17,33 +17,8 @@ from dify_plugin.core.documentation.schema_doc import docs
|
|
|
17
17
|
from dify_plugin.core.utils.yaml_loader import load_yaml_file
|
|
18
18
|
from dify_plugin.entities import I18nObject
|
|
19
19
|
from dify_plugin.entities.model.message import PromptMessageTool
|
|
20
|
-
from dify_plugin.entities.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class LogMetadata(str, Enum):
|
|
24
|
-
STARTED_AT = "started_at"
|
|
25
|
-
FINISHED_AT = "finished_at"
|
|
26
|
-
ELAPSED_TIME = "elapsed_time"
|
|
27
|
-
TOTAL_PRICE = "total_price"
|
|
28
|
-
TOTAL_TOKENS = "total_tokens"
|
|
29
|
-
PROVIDER = "provider"
|
|
30
|
-
CURRENCY = "currency"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class CommonParameterType(Enum):
|
|
34
|
-
SECRET_INPUT = "secret-input"
|
|
35
|
-
TEXT_INPUT = "text-input"
|
|
36
|
-
SELECT = "select"
|
|
37
|
-
STRING = "string"
|
|
38
|
-
NUMBER = "number"
|
|
39
|
-
FILE = "file"
|
|
40
|
-
FILES = "files"
|
|
41
|
-
BOOLEAN = "boolean"
|
|
42
|
-
APP_SELECTOR = "app-selector"
|
|
43
|
-
MODEL_SELECTOR = "model-selector"
|
|
44
|
-
# TOOL_SELECTOR = "tool-selector"
|
|
45
|
-
TOOLS_SELECTOR = "array[tools]"
|
|
46
|
-
ANY = "any"
|
|
20
|
+
from dify_plugin.entities.oauth import OAuthSchema
|
|
21
|
+
from dify_plugin.entities.provider_config import CommonParameterType, LogMetadata, ProviderConfig
|
|
47
22
|
|
|
48
23
|
|
|
49
24
|
class ToolRuntime(BaseModel):
|
|
@@ -360,6 +335,10 @@ class ToolProviderConfiguration(BaseModel):
|
|
|
360
335
|
alias="credentials_for_provider",
|
|
361
336
|
description="The credentials schema of the tool provider",
|
|
362
337
|
)
|
|
338
|
+
oauth_schema: Optional[OAuthSchema] = Field(
|
|
339
|
+
default=None,
|
|
340
|
+
description="The OAuth schema of the tool provider if OAuth is supported",
|
|
341
|
+
)
|
|
363
342
|
tools: list[ToolConfiguration] = Field(default=[], description="The tools of the tool provider")
|
|
364
343
|
extra: ToolProviderConfigurationExtra
|
|
365
344
|
|
|
@@ -415,6 +394,7 @@ class ToolProviderType(Enum):
|
|
|
415
394
|
API = "api"
|
|
416
395
|
APP = "app"
|
|
417
396
|
DATASET_RETRIEVAL = "dataset-retrieval"
|
|
397
|
+
MCP = "mcp"
|
|
418
398
|
|
|
419
399
|
@classmethod
|
|
420
400
|
def value_of(cls, value: str) -> "ToolProviderType":
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
|
+
import shutil
|
|
3
4
|
import signal
|
|
4
5
|
import subprocess
|
|
6
|
+
import tempfile
|
|
5
7
|
import threading
|
|
6
8
|
import uuid
|
|
7
9
|
from collections.abc import Generator
|
|
@@ -56,6 +58,7 @@ class PluginRunner:
|
|
|
56
58
|
self.config = config
|
|
57
59
|
self.plugin_package_path = plugin_package_path
|
|
58
60
|
self.extra_args = extra_args or []
|
|
61
|
+
self.resources_need_to_be_cleaned = []
|
|
59
62
|
|
|
60
63
|
# create pipe to communicate with the plugin
|
|
61
64
|
self.stdout_pipe_read, self.stdout_pipe_write = os.pipe()
|
|
@@ -71,8 +74,26 @@ class PluginRunner:
|
|
|
71
74
|
|
|
72
75
|
logger.info(f"Running plugin from {plugin_package_path}")
|
|
73
76
|
|
|
77
|
+
# check if plugin is a directory
|
|
78
|
+
if os.path.isdir(plugin_package_path):
|
|
79
|
+
logger.info("plugin source directory detected, building plugin")
|
|
80
|
+
with tempfile.TemporaryDirectory(delete=False) as temp_dir:
|
|
81
|
+
output_path = os.path.join(temp_dir, "plugin.difypkg")
|
|
82
|
+
self._build_plugin(plugin_package_path, output_path)
|
|
83
|
+
self.plugin_package_path = output_path
|
|
84
|
+
logger.info(f"Plugin built in {self.plugin_package_path}")
|
|
85
|
+
self.resources_need_to_be_cleaned.append(temp_dir)
|
|
86
|
+
|
|
74
87
|
self.process = subprocess.Popen( # noqa: S603
|
|
75
|
-
[
|
|
88
|
+
[
|
|
89
|
+
self.config.dify_cli_path,
|
|
90
|
+
"plugin",
|
|
91
|
+
"run",
|
|
92
|
+
self.plugin_package_path,
|
|
93
|
+
"--response-format",
|
|
94
|
+
"json",
|
|
95
|
+
*self.extra_args,
|
|
96
|
+
],
|
|
76
97
|
stdout=self.stdout_pipe_write,
|
|
77
98
|
stderr=self.stderr_pipe_write,
|
|
78
99
|
stdin=self.stdin_pipe_read,
|
|
@@ -98,6 +119,13 @@ class PluginRunner:
|
|
|
98
119
|
|
|
99
120
|
logger.info("Plugin ready")
|
|
100
121
|
|
|
122
|
+
def _build_plugin(self, package_path: str, output_path: str):
|
|
123
|
+
# build plugin
|
|
124
|
+
output = subprocess.check_output( # noqa: S603
|
|
125
|
+
[self.config.dify_cli_path, "plugin", "package", package_path, "-o", output_path],
|
|
126
|
+
)
|
|
127
|
+
logger.info(output.decode("utf-8"))
|
|
128
|
+
|
|
101
129
|
def _close(self):
|
|
102
130
|
with self.stop_flag_lock:
|
|
103
131
|
if self.stop_flag:
|
|
@@ -240,3 +268,6 @@ class PluginRunner:
|
|
|
240
268
|
|
|
241
269
|
def __exit__(self, exc_type, exc_value, traceback):
|
|
242
270
|
self._close()
|
|
271
|
+
|
|
272
|
+
for resource in self.resources_need_to_be_cleaned:
|
|
273
|
+
shutil.rmtree(resource)
|
|
@@ -2,6 +2,8 @@ from abc import ABC, abstractmethod
|
|
|
2
2
|
from collections.abc import Generator, Mapping
|
|
3
3
|
from typing import Any, Generic, Optional, TypeVar, final
|
|
4
4
|
|
|
5
|
+
from werkzeug import Request
|
|
6
|
+
|
|
5
7
|
from dify_plugin.core.runtime import Session
|
|
6
8
|
from dify_plugin.entities.agent import AgentInvokeMessage
|
|
7
9
|
from dify_plugin.entities.tool import LogMetadata, ToolInvokeMessage, ToolParameter, ToolRuntime, ToolSelector
|
|
@@ -222,13 +224,24 @@ class ToolLike(ABC, Generic[T]):
|
|
|
222
224
|
return tool_parameters
|
|
223
225
|
|
|
224
226
|
|
|
225
|
-
class ToolProvider
|
|
227
|
+
class ToolProvider:
|
|
226
228
|
def validate_credentials(self, credentials: dict):
|
|
227
229
|
return self._validate_credentials(credentials)
|
|
228
230
|
|
|
229
|
-
@abstractmethod
|
|
230
231
|
def _validate_credentials(self, credentials: dict):
|
|
231
|
-
|
|
232
|
+
raise NotImplementedError("This method should be implemented by a subclass")
|
|
233
|
+
|
|
234
|
+
def oauth_get_authorization_url(self, system_credentials: Mapping[str, Any]) -> str:
|
|
235
|
+
return self._oauth_get_authorization_url(system_credentials)
|
|
236
|
+
|
|
237
|
+
def _oauth_get_authorization_url(self, system_credentials: Mapping[str, Any]) -> str:
|
|
238
|
+
raise NotImplementedError("This method should be implemented by a subclass")
|
|
239
|
+
|
|
240
|
+
def oauth_get_credentials(self, system_credentials: Mapping[str, Any], request: Request) -> Mapping[str, Any]:
|
|
241
|
+
return self._oauth_get_credentials(system_credentials, request)
|
|
242
|
+
|
|
243
|
+
def _oauth_get_credentials(self, system_credentials: Mapping[str, Any], request: Request) -> Mapping[str, Any]:
|
|
244
|
+
raise NotImplementedError("This method should be implemented by a subclass")
|
|
232
245
|
|
|
233
246
|
|
|
234
247
|
class Tool(ToolLike[ToolInvokeMessage]):
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from collections.abc import Mapping
|
|
2
|
+
from typing import Any, Protocol
|
|
3
|
+
|
|
4
|
+
from werkzeug import Request
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OAuthProviderProtocol(Protocol):
|
|
8
|
+
def oauth_get_authorization_url(self, system_credentials: Mapping[str, Any]) -> str:
|
|
9
|
+
"""
|
|
10
|
+
Get the authorization url
|
|
11
|
+
:param system_credentials: system credentials
|
|
12
|
+
:return: authorization url
|
|
13
|
+
"""
|
|
14
|
+
...
|
|
15
|
+
|
|
16
|
+
def oauth_get_credentials(
|
|
17
|
+
self,
|
|
18
|
+
system_credentials: Mapping[str, Any],
|
|
19
|
+
request: Request,
|
|
20
|
+
) -> Mapping[str, Any]:
|
|
21
|
+
"""
|
|
22
|
+
Get the credentials
|
|
23
|
+
:param request: request
|
|
24
|
+
:param system_credentials: system credentials
|
|
25
|
+
:return: credentials
|
|
26
|
+
"""
|
|
27
|
+
...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dify_plugin"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.2"
|
|
4
4
|
description = "Dify Plugin SDK"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "langgenius", email = "hello@dify.ai" },
|
|
@@ -13,7 +13,6 @@ dependencies = [
|
|
|
13
13
|
"httpx~=0.28.1",
|
|
14
14
|
"pydantic_settings>=2.5.0,<3.0.0",
|
|
15
15
|
"pydantic>=2.8.2",
|
|
16
|
-
"pydub~=0.25.1",
|
|
17
16
|
"pyyaml~=6.0.1",
|
|
18
17
|
"requests~=2.32.3",
|
|
19
18
|
"socksio==1.0.0",
|
|
@@ -3,9 +3,9 @@ import json
|
|
|
3
3
|
import flask.cli
|
|
4
4
|
from flask import Flask, Response, jsonify, request
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
from tests.consts.mockserver import OPENAI_MOCK_SERVER_PORT
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
flask.cli.show_server_banner = lambda *args: None
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def openai_server_mock():
|
|
@@ -40,4 +40,4 @@ def openai_server_mock():
|
|
|
40
40
|
}
|
|
41
41
|
)
|
|
42
42
|
|
|
43
|
-
app.run(port=
|
|
43
|
+
app.run(port=OPENAI_MOCK_SERVER_PORT)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
OPENAI_MOCK_SERVER_PORT = 11451
|
|
@@ -6,7 +6,7 @@ from dify_plugin.entities.model import ModelType
|
|
|
6
6
|
from dify_plugin.entities.model.llm import LLMResultChunk
|
|
7
7
|
from dify_plugin.entities.model.message import UserPromptMessage
|
|
8
8
|
from dify_plugin.integration.run import PluginRunner
|
|
9
|
-
from tests.
|
|
9
|
+
from tests.consts.mockserver import OPENAI_MOCK_SERVER_PORT
|
|
10
10
|
|
|
11
11
|
_MARKETPLACE_API_URL = "https://marketplace.dify.ai"
|
|
12
12
|
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from dify_plugin.interfaces.tool import ToolProvider
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_construct_tool_provider():
|
|
7
|
+
"""
|
|
8
|
+
Test that the ToolProvider can be constructed without implementing any methods
|
|
9
|
+
"""
|
|
10
|
+
provider = ToolProvider()
|
|
11
|
+
assert provider is not None
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_oauth_get_authorization_url():
|
|
15
|
+
"""
|
|
16
|
+
Test that the ToolProvider can get the authorization url
|
|
17
|
+
"""
|
|
18
|
+
provider = ToolProvider()
|
|
19
|
+
with pytest.raises(NotImplementedError):
|
|
20
|
+
provider.oauth_get_authorization_url({})
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/serverless/request_reader.py
RENAMED
|
File without changes
|
{dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/core/server/serverless/response_writer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/large_language_model.py
RENAMED
|
File without changes
|
|
File without changes
|
{dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/openai_compatible/__init__.py
RENAMED
|
File without changes
|
{dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/openai_compatible/common.py
RENAMED
|
File without changes
|
{dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/openai_compatible/llm.py
RENAMED
|
File without changes
|
{dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/openai_compatible/provider.py
RENAMED
|
File without changes
|
{dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/openai_compatible/rerank.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/openai_compatible/tts.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/interfaces/model/text_embedding_model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/workflow_node/parameter_extractor.py
RENAMED
|
File without changes
|
{dify_plugin-0.3.0 → dify_plugin-0.3.2}/dify_plugin/invocations/workflow_node/question_classifier.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|