Merge remote-tracking branch 'origin/main' into feat/trigger

This commit is contained in:
lyzno1
2025-10-23 11:54:35 +08:00
366 changed files with 5222 additions and 3901 deletions

View File

@ -58,6 +58,7 @@ def setup_account(request) -> Generator[Account, None, None]:
name=name,
password=secrets.token_hex(16),
ip_address="localhost",
language="en-US",
)
with _CACHED_APP.test_request_context():

View File

@ -2299,6 +2299,7 @@ class TestRegisterService:
name=admin_name,
password=admin_password,
ip_address=ip_address,
language="en-US",
)
# Verify account was created
@ -2348,6 +2349,7 @@ class TestRegisterService:
name=admin_name,
password=admin_password,
ip_address=ip_address,
language="en-US",
)
# Verify no entities were created (rollback worked)

View File

@ -6,6 +6,7 @@ from faker import Faker
from core.tools.entities.api_entities import ToolProviderApiEntity
from core.tools.entities.common_entities import I18nObject
from core.tools.entities.tool_entities import ToolProviderType
from libs.uuid_utils import uuidv7
from models.tools import ApiToolProvider, BuiltinToolProvider, MCPToolProvider, WorkflowToolProvider
from services.plugin.plugin_service import PluginService
from services.tools.tools_transform_service import ToolTransformService
@ -67,6 +68,7 @@ class TestToolTransformService:
)
elif provider_type == "workflow":
provider = WorkflowToolProvider(
id=str(uuidv7()),
name=fake.company(),
description=fake.text(max_nb_chars=100),
icon='{"background": "#FF6B6B", "content": "🔧"}',
@ -759,6 +761,7 @@ class TestToolTransformService:
# Create workflow tool provider
provider = WorkflowToolProvider(
id=str(uuidv7()),
name=fake.company(),
description=fake.text(max_nb_chars=100),
icon='{"background": "#FF6B6B", "content": "🔧"}',

View File

@ -109,3 +109,83 @@ def test_parse_openapi_to_tool_bundle_properties_all_of(app):
assert tool_bundles[0].parameters[0].llm_description == "desc prop1"
# TODO: support enum in OpenAPI
# assert set(tool_bundles[0].parameters[0].options) == {"option1", "option2", "option3"}
def test_parse_openapi_to_tool_bundle_default_value_type_casting(app):
"""
Test that default values are properly cast to match parameter types.
This addresses the issue where array default values like [] cause validation errors
when parameter type is inferred as string/number/boolean.
"""
openapi = {
"openapi": "3.0.0",
"info": {"title": "Test API", "version": "1.0.0"},
"servers": [{"url": "https://example.com"}],
"paths": {
"/product/create": {
"post": {
"operationId": "createProduct",
"summary": "Create a product",
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"categories": {
"description": "List of category identifiers",
"default": [],
"type": "array",
"items": {"type": "string"},
},
"name": {
"description": "Product name",
"default": "Default Product",
"type": "string",
},
"price": {"description": "Product price", "default": 0.0, "type": "number"},
"available": {
"description": "Product availability",
"default": True,
"type": "boolean",
},
},
}
}
}
},
"responses": {"200": {"description": "Default Response"}},
}
}
},
}
with app.test_request_context():
tool_bundles = ApiBasedToolSchemaParser.parse_openapi_to_tool_bundle(openapi)
assert len(tool_bundles) == 1
bundle = tool_bundles[0]
assert len(bundle.parameters) == 4
# Find parameters by name
params_by_name = {param.name: param for param in bundle.parameters}
# Check categories parameter (array type with [] default)
categories_param = params_by_name["categories"]
assert categories_param.type == "array" # Will be detected by _get_tool_parameter_type
assert categories_param.default is None # Array default [] is converted to None
# Check name parameter (string type with string default)
name_param = params_by_name["name"]
assert name_param.type == "string"
assert name_param.default == "Default Product"
# Check price parameter (number type with number default)
price_param = params_by_name["price"]
assert price_param.type == "number"
assert price_param.default == 0.0
# Check available parameter (boolean type with boolean default)
available_param = params_by_name["available"]
assert available_param.type == "boolean"
assert available_param.default is True

View File

@ -1,5 +1,5 @@
from constants import COOKIE_NAME_ACCESS_TOKEN
from libs.token import extract_access_token
from constants import COOKIE_NAME_ACCESS_TOKEN, COOKIE_NAME_WEBAPP_ACCESS_TOKEN
from libs.token import extract_access_token, extract_webapp_access_token
class MockRequest:
@ -14,10 +14,12 @@ def test_extract_access_token():
return MockRequest(headers, cookies, args)
test_cases = [
(_mock_request({"Authorization": "Bearer 123"}, {}, {}), "123"),
(_mock_request({}, {COOKIE_NAME_ACCESS_TOKEN: "123"}, {}), "123"),
(_mock_request({}, {}, {}), None),
(_mock_request({"Authorization": "Bearer_aaa 123"}, {}, {}), None),
(_mock_request({"Authorization": "Bearer 123"}, {}, {}), "123", "123"),
(_mock_request({}, {COOKIE_NAME_ACCESS_TOKEN: "123"}, {}), "123", None),
(_mock_request({}, {}, {}), None, None),
(_mock_request({"Authorization": "Bearer_aaa 123"}, {}, {}), None, None),
(_mock_request({}, {COOKIE_NAME_WEBAPP_ACCESS_TOKEN: "123"}, {}), None, "123"),
]
for request, expected in test_cases:
assert extract_access_token(request) == expected # pyright: ignore[reportArgumentType]
for request, expected_console, expected_webapp in test_cases:
assert extract_access_token(request) == expected_console # pyright: ignore[reportArgumentType]
assert extract_webapp_access_token(request) == expected_webapp # pyright: ignore[reportArgumentType]

View File

@ -893,7 +893,7 @@ class TestRegisterService:
mock_dify_setup.return_value = mock_dify_setup_instance
# Execute test
RegisterService.setup("admin@example.com", "Admin User", "password123", "192.168.1.1")
RegisterService.setup("admin@example.com", "Admin User", "password123", "192.168.1.1", "en-US")
# Verify results
mock_create_account.assert_called_once_with(
@ -925,6 +925,7 @@ class TestRegisterService:
"Admin User",
"password123",
"192.168.1.1",
"en-US",
)
# Verify rollback operations were called