mirror of https://github.com/langgenius/dify.git
feat: plugin call dify
This commit is contained in:
parent
603187393a
commit
364df36ac4
|
|
@ -238,3 +238,6 @@ WORKFLOW_CALL_MAX_DEPTH=5
|
|||
# App configuration
|
||||
APP_MAX_EXECUTION_TIME=1200
|
||||
|
||||
# Plugin configuration
|
||||
PLUGIN_INNER_API_URL=http://127.0.0.1:5002
|
||||
PLUGIN_INNER_API_KEY=lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi
|
||||
|
|
|
|||
|
|
@ -47,6 +47,19 @@ class CodeExecutionSandboxConfig(BaseSettings):
|
|||
default='dify-sandbox',
|
||||
)
|
||||
|
||||
class PluginConfig(BaseSettings):
|
||||
"""
|
||||
Plugin configs
|
||||
"""
|
||||
PLUGIN_INNER_API_URL: str = Field(
|
||||
description='Plugin inner API URL',
|
||||
default='http://plugin:8194',
|
||||
)
|
||||
|
||||
PLUGIN_INNER_API_KEY: str = Field(
|
||||
description='Plugin inner API key',
|
||||
default='dify-inner-api-key',
|
||||
)
|
||||
|
||||
class EndpointConfig(BaseSettings):
|
||||
"""
|
||||
|
|
@ -431,6 +444,7 @@ class FeatureConfig(
|
|||
AppExecutionConfig,
|
||||
BillingConfig,
|
||||
CodeExecutionSandboxConfig,
|
||||
PluginConfig,
|
||||
DataSetConfig,
|
||||
EndpointConfig,
|
||||
FileAccessConfig,
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ from libs.external_api import ExternalApi
|
|||
bp = Blueprint('inner_api', __name__, url_prefix='/inner/api')
|
||||
api = ExternalApi(bp)
|
||||
|
||||
from .plugin import plugin
|
||||
from .workspace import workspace
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
from .plugin import *
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
|
||||
from flask_restful import Resource, reqparse
|
||||
|
||||
from controllers.console.setup import setup_required
|
||||
from controllers.inner_api import api
|
||||
from controllers.inner_api.plugin.wraps import get_tenant
|
||||
from controllers.inner_api.wraps import plugin_inner_api_only
|
||||
from libs.helper import compact_generate_response
|
||||
from models.account import Tenant
|
||||
from services.plugin.plugin_invoke_service import PluginInvokeService
|
||||
|
||||
|
||||
class PluginInvokeModelApi(Resource):
|
||||
@setup_required
|
||||
@plugin_inner_api_only
|
||||
@get_tenant
|
||||
def post(self, user_id: str, tenant_model: Tenant):
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('provider', type=dict, required=True, location='json')
|
||||
parser.add_argument('model', type=dict, required=True, location='json')
|
||||
parser.add_argument('parameters', type=dict, required=True, location='json')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
class PluginInvokeToolApi(Resource):
|
||||
@setup_required
|
||||
@plugin_inner_api_only
|
||||
@get_tenant
|
||||
def post(self, user_id: str, tenant_model: Tenant):
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('provider', type=dict, required=True, location='json')
|
||||
parser.add_argument('tool', type=dict, required=True, location='json')
|
||||
parser.add_argument('parameters', type=dict, required=True, location='json')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
response = PluginInvokeService.invoke_tool(user_id, tenant_model,
|
||||
args['provider'], args['tool'],
|
||||
args['parameters'])
|
||||
return compact_generate_response(response)
|
||||
|
||||
|
||||
class PluginInvokeNodeApi(Resource):
|
||||
@setup_required
|
||||
@plugin_inner_api_only
|
||||
@get_tenant
|
||||
def post(self, user_id: str, tenant_model: Tenant):
|
||||
parser = reqparse.RequestParser()
|
||||
args = parser.parse_args()
|
||||
|
||||
return {
|
||||
'message': 'success'
|
||||
}
|
||||
|
||||
|
||||
api.add_resource(PluginInvokeModelApi, '/invoke/model')
|
||||
api.add_resource(PluginInvokeToolApi, '/invoke/tool')
|
||||
api.add_resource(PluginInvokeNodeApi, '/invoke/node')
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
from collections.abc import Callable
|
||||
from functools import wraps
|
||||
from typing import Optional
|
||||
|
||||
from flask_restful import reqparse
|
||||
|
||||
from extensions.ext_database import db
|
||||
from models.account import Tenant
|
||||
|
||||
|
||||
def get_tenant(view: Optional[Callable] = None):
|
||||
def decorator(view_func):
|
||||
@wraps(view_func)
|
||||
def decorated_view(*args, **kwargs):
|
||||
# fetch json body
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('tenant_id', type=str, required=True, location='json')
|
||||
parser.add_argument('user_id', type=str, required=True, location='json')
|
||||
|
||||
kwargs = parser.parse_args()
|
||||
|
||||
user_id = kwargs.get('user_id')
|
||||
tenant_id = kwargs.get('tenant_id')
|
||||
|
||||
del kwargs['tenant_id']
|
||||
del kwargs['user_id']
|
||||
|
||||
try:
|
||||
tenant_model = db.session.query(Tenant).filter(
|
||||
Tenant.id == tenant_id,
|
||||
).first()
|
||||
except Exception:
|
||||
raise ValueError('tenant not found')
|
||||
|
||||
if not tenant_model:
|
||||
raise ValueError('tenant not found')
|
||||
|
||||
kwargs['tenant_model'] = tenant_model
|
||||
kwargs['user_id'] = user_id
|
||||
|
||||
return view_func(*args, **kwargs)
|
||||
return decorated_view
|
||||
|
||||
if view is None:
|
||||
return decorator
|
||||
else:
|
||||
return decorator(view)
|
||||
|
|
@ -2,7 +2,7 @@ from flask_restful import Resource, reqparse
|
|||
|
||||
from controllers.console.setup import setup_required
|
||||
from controllers.inner_api import api
|
||||
from controllers.inner_api.wraps import inner_api_only
|
||||
from controllers.inner_api.wraps import enterprise_inner_api_only
|
||||
from events.tenant_event import tenant_was_created
|
||||
from models.account import Account
|
||||
from services.account_service import TenantService
|
||||
|
|
@ -11,7 +11,7 @@ from services.account_service import TenantService
|
|||
class EnterpriseWorkspace(Resource):
|
||||
|
||||
@setup_required
|
||||
@inner_api_only
|
||||
@enterprise_inner_api_only
|
||||
def post(self):
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('name', type=str, required=True, location='json')
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@ from hmac import new as hmac_new
|
|||
|
||||
from flask import abort, current_app, request
|
||||
|
||||
from configs import dify_config
|
||||
from extensions.ext_database import db
|
||||
from models.model import EndUser
|
||||
|
||||
|
||||
def inner_api_only(view):
|
||||
def enterprise_inner_api_only(view):
|
||||
@wraps(view)
|
||||
def decorated(*args, **kwargs):
|
||||
if not current_app.config['INNER_API']:
|
||||
|
|
@ -25,7 +26,7 @@ def inner_api_only(view):
|
|||
return decorated
|
||||
|
||||
|
||||
def inner_api_user_auth(view):
|
||||
def enterprise_inner_api_user_auth(view):
|
||||
@wraps(view)
|
||||
def decorated(*args, **kwargs):
|
||||
if not current_app.config['INNER_API']:
|
||||
|
|
@ -59,3 +60,18 @@ def inner_api_user_auth(view):
|
|||
return view(*args, **kwargs)
|
||||
|
||||
return decorated
|
||||
|
||||
def plugin_inner_api_only(view):
|
||||
@wraps(view)
|
||||
def decorated(*args, **kwargs):
|
||||
if not dify_config.PLUGIN_INNER_API_KEY:
|
||||
abort(404)
|
||||
|
||||
# get header 'X-Inner-Api-Key'
|
||||
inner_api_key = request.headers.get('X-Inner-Api-Key')
|
||||
if not inner_api_key or inner_api_key != dify_config.PLUGIN_INNER_API_KEY:
|
||||
abort(404)
|
||||
|
||||
return view(*args, **kwargs)
|
||||
|
||||
return decorated
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
from collections.abc import Generator
|
||||
from typing import Any
|
||||
|
||||
from core.tools.entities.tool_entities import ToolInvokeMessage
|
||||
from models.account import Tenant
|
||||
|
||||
|
||||
class PluginInvokeService:
|
||||
@classmethod
|
||||
def invoke_tool(cls, user_id: str, tenant: Tenant,
|
||||
tool_provider: str, tool_name: str,
|
||||
tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:
|
||||
"""
|
||||
Invokes a tool with the given user ID and tool parameters.
|
||||
"""
|
||||
|
||||
Loading…
Reference in New Issue