mirror of
https://github.com/langgenius/dify.git
synced 2026-09-08 11:04:27 +08:00
refactor: make explore localization request-driven (#41798)
This commit is contained in:
parent
8504aaa0ef
commit
cea89f784f
@ -7,17 +7,17 @@ from pydantic import BaseModel, Field, computed_field, field_validator
|
|||||||
from controllers.common.schema import query_params_from_model, register_response_schema_models, register_schema_models
|
from controllers.common.schema import query_params_from_model, register_response_schema_models, register_schema_models
|
||||||
from controllers.console import console_ns
|
from controllers.console import console_ns
|
||||||
from controllers.console.explore.error import RecommendedAppNotFoundError
|
from controllers.console.explore.error import RecommendedAppNotFoundError
|
||||||
from controllers.console.wraps import account_initialization_required, model_validate, with_current_user
|
from controllers.console.flask_admission import console_account_admission
|
||||||
|
from controllers.console.wraps import model_validate
|
||||||
from extensions.ext_application_services import application_services
|
from extensions.ext_application_services import application_services
|
||||||
from fields.base import ResponseModel
|
from fields.base import ResponseModel
|
||||||
from libs.helper import build_icon_url, dump_response
|
from libs.helper import build_icon_url, dump_response
|
||||||
from libs.login import login_required
|
from machinery.context import RequestContext
|
||||||
from models import Account
|
|
||||||
from services.recommended_app_query_service import RecommendedAppNotFoundError as RecommendedAppQueryNotFoundError
|
from services.recommended_app_query_service import RecommendedAppNotFoundError as RecommendedAppQueryNotFoundError
|
||||||
|
|
||||||
|
|
||||||
class RecommendedAppsQuery(BaseModel):
|
class RecommendedAppsQuery(BaseModel):
|
||||||
language: str | None = Field(default=None, description="Language code for recommended app localization")
|
language: str = Field(default="en-US", description="Language code for recommended app localization")
|
||||||
|
|
||||||
|
|
||||||
class RecommendedAppInfoResponse(ResponseModel):
|
class RecommendedAppInfoResponse(ResponseModel):
|
||||||
@ -97,16 +97,13 @@ register_response_schema_models(
|
|||||||
class RecommendedAppListApi(Resource):
|
class RecommendedAppListApi(Resource):
|
||||||
@console_ns.doc(params=query_params_from_model(RecommendedAppsQuery))
|
@console_ns.doc(params=query_params_from_model(RecommendedAppsQuery))
|
||||||
@console_ns.response(200, "Success", console_ns.models[RecommendedAppListResponse.__name__])
|
@console_ns.response(200, "Success", console_ns.models[RecommendedAppListResponse.__name__])
|
||||||
@login_required
|
@console_account_admission()
|
||||||
@account_initialization_required
|
|
||||||
@with_current_user
|
|
||||||
@model_validate(RecommendedAppsQuery)
|
@model_validate(RecommendedAppsQuery)
|
||||||
def get(self, req_data: RecommendedAppsQuery, current_user: Account):
|
def get(self, req_data: RecommendedAppsQuery, _request_context: RequestContext):
|
||||||
return dump_response(
|
return dump_response(
|
||||||
RecommendedAppListResponse,
|
RecommendedAppListResponse,
|
||||||
application_services().recommended_app_queries.list_recommended(
|
application_services().recommended_app_queries.list_recommended(
|
||||||
requested_language=req_data.language,
|
language=req_data.language,
|
||||||
interface_language=current_user.interface_language,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -115,16 +112,13 @@ class RecommendedAppListApi(Resource):
|
|||||||
class LearnDifyAppListApi(Resource):
|
class LearnDifyAppListApi(Resource):
|
||||||
@console_ns.doc(params=query_params_from_model(RecommendedAppsQuery))
|
@console_ns.doc(params=query_params_from_model(RecommendedAppsQuery))
|
||||||
@console_ns.response(200, "Success", console_ns.models[LearnDifyAppListResponse.__name__])
|
@console_ns.response(200, "Success", console_ns.models[LearnDifyAppListResponse.__name__])
|
||||||
@login_required
|
@console_account_admission()
|
||||||
@account_initialization_required
|
|
||||||
@with_current_user
|
|
||||||
@model_validate(RecommendedAppsQuery)
|
@model_validate(RecommendedAppsQuery)
|
||||||
def get(self, req_data: RecommendedAppsQuery, current_user: Account):
|
def get(self, req_data: RecommendedAppsQuery, _request_context: RequestContext):
|
||||||
return dump_response(
|
return dump_response(
|
||||||
LearnDifyAppListResponse,
|
LearnDifyAppListResponse,
|
||||||
application_services().recommended_app_queries.list_learn_dify(
|
application_services().recommended_app_queries.list_learn_dify(
|
||||||
requested_language=req_data.language,
|
language=req_data.language,
|
||||||
interface_language=current_user.interface_language,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -133,9 +127,8 @@ class LearnDifyAppListApi(Resource):
|
|||||||
class RecommendedAppApi(Resource):
|
class RecommendedAppApi(Resource):
|
||||||
@console_ns.response(200, "Success", console_ns.models[RecommendedAppDetailResponse.__name__])
|
@console_ns.response(200, "Success", console_ns.models[RecommendedAppDetailResponse.__name__])
|
||||||
@console_ns.response(404, "Recommended app not found")
|
@console_ns.response(404, "Recommended app not found")
|
||||||
@login_required
|
@console_account_admission()
|
||||||
@account_initialization_required
|
def get(self, _request_context: RequestContext, app_id: UUID):
|
||||||
def get(self, app_id: UUID):
|
|
||||||
try:
|
try:
|
||||||
result = application_services().recommended_app_queries.get_detail(str(app_id))
|
result = application_services().recommended_app_queries.get_detail(str(app_id))
|
||||||
except RecommendedAppQueryNotFoundError:
|
except RecommendedAppQueryNotFoundError:
|
||||||
|
|||||||
@ -6507,7 +6507,7 @@ Check if dataset is in use
|
|||||||
|
|
||||||
| Name | Located in | Description | Required | Schema |
|
| Name | Located in | Description | Required | Schema |
|
||||||
| ---- | ---------- | ----------- | -------- | ------ |
|
| ---- | ---------- | ----------- | -------- | ------ |
|
||||||
| language | query | Language code for recommended app localization | No | string |
|
| language | query | Language code for recommended app localization | No | string, <br>**Default:** en-US |
|
||||||
|
|
||||||
#### Responses
|
#### Responses
|
||||||
|
|
||||||
@ -6520,7 +6520,7 @@ Check if dataset is in use
|
|||||||
|
|
||||||
| Name | Located in | Description | Required | Schema |
|
| Name | Located in | Description | Required | Schema |
|
||||||
| ---- | ---------- | ----------- | -------- | ------ |
|
| ---- | ---------- | ----------- | -------- | ------ |
|
||||||
| language | query | Language code for recommended app localization | No | string |
|
| language | query | Language code for recommended app localization | No | string, <br>**Default:** en-US |
|
||||||
|
|
||||||
#### Responses
|
#### Responses
|
||||||
|
|
||||||
@ -21331,7 +21331,7 @@ Model class for provider quota configuration.
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
| ---- | ---- | ----------- | -------- |
|
| ---- | ---- | ----------- | -------- |
|
||||||
| language | string | Language code for recommended app localization | No |
|
| language | string, <br>**Default:** en-US | Language code for recommended app localization | No |
|
||||||
|
|
||||||
#### RedirectResponse
|
#### RedirectResponse
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,8 @@ from collections.abc import Sequence
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, NamedTuple, Protocol
|
from typing import Any, NamedTuple, Protocol
|
||||||
|
|
||||||
|
from constants.languages import languages
|
||||||
|
|
||||||
_DEFAULT_LANGUAGE = "en-US"
|
_DEFAULT_LANGUAGE = "en-US"
|
||||||
|
|
||||||
|
|
||||||
@ -37,6 +39,7 @@ class ExploreBannerQueryService:
|
|||||||
if not self._enabled:
|
if not self._enabled:
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
|
language = language if language in languages else _DEFAULT_LANGUAGE
|
||||||
banners = tuple(self._banners.list_enabled(language))
|
banners = tuple(self._banners.list_enabled(language))
|
||||||
if banners or language == _DEFAULT_LANGUAGE:
|
if banners or language == _DEFAULT_LANGUAGE:
|
||||||
return banners
|
return banners
|
||||||
|
|||||||
@ -5,6 +5,8 @@ from typing import NamedTuple, Protocol
|
|||||||
|
|
||||||
from constants.languages import languages
|
from constants.languages import languages
|
||||||
|
|
||||||
|
_DEFAULT_LANGUAGE = "en-US"
|
||||||
|
|
||||||
|
|
||||||
class RecommendedAppInfoRecord(NamedTuple):
|
class RecommendedAppInfoRecord(NamedTuple):
|
||||||
id: str
|
id: str
|
||||||
@ -116,10 +118,9 @@ class RecommendedAppQueryService:
|
|||||||
def list_recommended(
|
def list_recommended(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
requested_language: str | None,
|
language: str,
|
||||||
interface_language: str | None,
|
|
||||||
) -> RecommendedAppListResult:
|
) -> RecommendedAppListResult:
|
||||||
language = self._resolve_language(requested_language, interface_language)
|
language = language if language in languages else _DEFAULT_LANGUAGE
|
||||||
page = self._catalog.list_recommended(language)
|
page = self._catalog.list_recommended(language)
|
||||||
|
|
||||||
return RecommendedAppListResult(
|
return RecommendedAppListResult(
|
||||||
@ -130,10 +131,9 @@ class RecommendedAppQueryService:
|
|||||||
def list_learn_dify(
|
def list_learn_dify(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
requested_language: str | None,
|
language: str,
|
||||||
interface_language: str | None,
|
|
||||||
) -> LearnDifyAppListResult:
|
) -> LearnDifyAppListResult:
|
||||||
language = self._resolve_language(requested_language, interface_language)
|
language = language if language in languages else _DEFAULT_LANGUAGE
|
||||||
page = self._catalog.list_learn_dify(language)
|
page = self._catalog.list_learn_dify(language)
|
||||||
return LearnDifyAppListResult(recommended_apps=self._with_trial_status(page.recommended_apps))
|
return LearnDifyAppListResult(recommended_apps=self._with_trial_status(page.recommended_apps))
|
||||||
|
|
||||||
@ -176,11 +176,3 @@ class RecommendedAppQueryService:
|
|||||||
)
|
)
|
||||||
for app in apps
|
for app in apps
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _resolve_language(requested_language: str | None, interface_language: str | None) -> str:
|
|
||||||
if requested_language and requested_language in languages:
|
|
||||||
return requested_language
|
|
||||||
if interface_language:
|
|
||||||
return interface_language
|
|
||||||
return languages[0]
|
|
||||||
|
|||||||
@ -110,7 +110,7 @@ class TestExploreBannerQueryService:
|
|||||||
assert service.list_for_language("fr-FR") == (record,)
|
assert service.list_for_language("fr-FR") == (record,)
|
||||||
assert banners.requested_languages == ["fr-FR"]
|
assert banners.requested_languages == ["fr-FR"]
|
||||||
|
|
||||||
def test_falls_back_to_en_us(self) -> None:
|
def test_falls_back_to_en_us_when_requested_translation_is_missing(self) -> None:
|
||||||
record = _record(title="fallback")
|
record = _record(title="fallback")
|
||||||
banners = FakeExploreBannerQuery({"en-US": (record,)})
|
banners = FakeExploreBannerQuery({"en-US": (record,)})
|
||||||
service = ExploreBannerQueryService(banners=banners, enabled=True)
|
service = ExploreBannerQueryService(banners=banners, enabled=True)
|
||||||
@ -118,6 +118,14 @@ class TestExploreBannerQueryService:
|
|||||||
assert service.list_for_language("es-ES") == (record,)
|
assert service.list_for_language("es-ES") == (record,)
|
||||||
assert banners.requested_languages == ["es-ES", "en-US"]
|
assert banners.requested_languages == ["es-ES", "en-US"]
|
||||||
|
|
||||||
|
def test_invalid_language_uses_en_us(self) -> None:
|
||||||
|
record = _record(title="fallback")
|
||||||
|
banners = FakeExploreBannerQuery({"en-US": (record,)})
|
||||||
|
service = ExploreBannerQueryService(banners=banners, enabled=True)
|
||||||
|
|
||||||
|
assert service.list_for_language("invalid") == (record,)
|
||||||
|
assert banners.requested_languages == ["en-US"]
|
||||||
|
|
||||||
def test_does_not_repeat_default_language_query(self) -> None:
|
def test_does_not_repeat_default_language_query(self) -> None:
|
||||||
banners = FakeExploreBannerQuery()
|
banners = FakeExploreBannerQuery()
|
||||||
service = ExploreBannerQueryService(banners=banners, enabled=True)
|
service = ExploreBannerQueryService(banners=banners, enabled=True)
|
||||||
|
|||||||
@ -7,7 +7,7 @@ from flask import Flask
|
|||||||
from pydantic import ValidationError
|
from pydantic import ValidationError
|
||||||
|
|
||||||
import controllers.console.explore.recommended_app as module
|
import controllers.console.explore.recommended_app as module
|
||||||
from models import Account
|
from machinery.context import RequestContext
|
||||||
from models.model import AppMode, IconType
|
from models.model import AppMode, IconType
|
||||||
from services.recommended_app_query_service import (
|
from services.recommended_app_query_service import (
|
||||||
LearnDifyAppListResult,
|
LearnDifyAppListResult,
|
||||||
@ -21,11 +21,13 @@ from services.recommended_app_query_service import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def make_account(interface_language: str | None) -> Account:
|
def _request_context() -> RequestContext:
|
||||||
account = Account(name="Test User", email="user@example.com")
|
return RequestContext(
|
||||||
account.id = "account-1"
|
request_id="request-1",
|
||||||
account.interface_language = interface_language
|
trace_id="trace-1",
|
||||||
return account
|
account_id="account-1",
|
||||||
|
active_workspace_id="workspace-1",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestRecommendedAppListApi:
|
class TestRecommendedAppListApi:
|
||||||
@ -44,17 +46,16 @@ class TestRecommendedAppListApi:
|
|||||||
return_value=SimpleNamespace(recommended_app_queries=queries),
|
return_value=SimpleNamespace(recommended_app_queries=queries),
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
result = method(api, module.RecommendedAppsQuery(language="en-US"), make_account("fr-FR"))
|
result = method(api, module.RecommendedAppsQuery(language="en-US"), _request_context())
|
||||||
|
|
||||||
queries.list_recommended.assert_called_once_with(
|
queries.list_recommended.assert_called_once_with(
|
||||||
requested_language="en-US",
|
language="en-US",
|
||||||
interface_language="fr-FR",
|
|
||||||
)
|
)
|
||||||
assert result == {"recommended_apps": [], "categories": []}
|
assert result == {"recommended_apps": [], "categories": []}
|
||||||
|
|
||||||
|
|
||||||
class TestLearnDifyAppListApi:
|
class TestLearnDifyAppListApi:
|
||||||
def test_get_with_language_param(self, app: Flask) -> None:
|
def test_get_uses_default_language(self, app: Flask) -> None:
|
||||||
api = module.LearnDifyAppListApi()
|
api = module.LearnDifyAppListApi()
|
||||||
method = unwrap(api.get)
|
method = unwrap(api.get)
|
||||||
|
|
||||||
@ -62,18 +63,17 @@ class TestLearnDifyAppListApi:
|
|||||||
queries.list_learn_dify.return_value = LearnDifyAppListResult(recommended_apps=())
|
queries.list_learn_dify.return_value = LearnDifyAppListResult(recommended_apps=())
|
||||||
|
|
||||||
with (
|
with (
|
||||||
app.test_request_context("/", query_string={"language": "en-US"}),
|
app.test_request_context("/"),
|
||||||
patch.object(
|
patch.object(
|
||||||
module,
|
module,
|
||||||
"application_services",
|
"application_services",
|
||||||
return_value=SimpleNamespace(recommended_app_queries=queries),
|
return_value=SimpleNamespace(recommended_app_queries=queries),
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
result = method(api, module.RecommendedAppsQuery(language="en-US"), make_account("fr-FR"))
|
result = method(api, module.RecommendedAppsQuery(), _request_context())
|
||||||
|
|
||||||
queries.list_learn_dify.assert_called_once_with(
|
queries.list_learn_dify.assert_called_once_with(
|
||||||
requested_language="en-US",
|
language="en-US",
|
||||||
interface_language="fr-FR",
|
|
||||||
)
|
)
|
||||||
assert result == {"recommended_apps": []}
|
assert result == {"recommended_apps": []}
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ class TestRecommendedAppApi:
|
|||||||
return_value=SimpleNamespace(recommended_app_queries=queries),
|
return_value=SimpleNamespace(recommended_app_queries=queries),
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
result = method(api, "11111111-1111-1111-1111-111111111111")
|
result = method(api, _request_context(), "11111111-1111-1111-1111-111111111111")
|
||||||
|
|
||||||
queries.get_detail.assert_called_once_with("11111111-1111-1111-1111-111111111111")
|
queries.get_detail.assert_called_once_with("11111111-1111-1111-1111-111111111111")
|
||||||
assert result == {
|
assert result == {
|
||||||
@ -130,7 +130,7 @@ class TestRecommendedAppApi:
|
|||||||
),
|
),
|
||||||
):
|
):
|
||||||
with pytest.raises(module.RecommendedAppNotFoundError) as exc_info:
|
with pytest.raises(module.RecommendedAppNotFoundError) as exc_info:
|
||||||
method(api, "11111111-1111-1111-1111-111111111111")
|
method(api, _request_context(), "11111111-1111-1111-1111-111111111111")
|
||||||
|
|
||||||
assert exc_info.value.data == {
|
assert exc_info.value.data == {
|
||||||
"code": "recommended_app_not_found",
|
"code": "recommended_app_not_found",
|
||||||
|
|||||||
@ -721,14 +721,12 @@ def test_build_application_services_wires_dynamic_recommended_catalog(
|
|||||||
)
|
)
|
||||||
with patch.object(recommended_app_catalog_gateway.Path, "read_text", return_value=builtin_payload):
|
with patch.object(recommended_app_catalog_gateway.Path, "read_text", return_value=builtin_payload):
|
||||||
result = services.recommended_app_queries.list_recommended(
|
result = services.recommended_app_queries.list_recommended(
|
||||||
requested_language="en-US",
|
language="en-US",
|
||||||
interface_language=None,
|
|
||||||
)
|
)
|
||||||
assert result.recommended_apps
|
assert result.recommended_apps
|
||||||
|
|
||||||
apply_config_overrides(monkeypatch, HOSTED_FETCH_APP_TEMPLATES_MODE="invalid")
|
apply_config_overrides(monkeypatch, HOSTED_FETCH_APP_TEMPLATES_MODE="invalid")
|
||||||
with pytest.raises(ValueError, match="invalid fetch recommended apps mode: invalid"):
|
with pytest.raises(ValueError, match="invalid fetch recommended apps mode: invalid"):
|
||||||
services.recommended_app_queries.list_recommended(
|
services.recommended_app_queries.list_recommended(
|
||||||
requested_language="en-US",
|
language="en-US",
|
||||||
interface_language=None,
|
|
||||||
)
|
)
|
||||||
|
|||||||
@ -2,7 +2,6 @@ from unittest.mock import MagicMock
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from constants.languages import languages
|
|
||||||
from services.recommended_app_query_service import (
|
from services.recommended_app_query_service import (
|
||||||
RecommendedAppCatalogPage,
|
RecommendedAppCatalogPage,
|
||||||
RecommendedAppDetailRecord,
|
RecommendedAppDetailRecord,
|
||||||
@ -83,17 +82,14 @@ def test_is_previewable_falls_back_to_catalog(expected: bool) -> None:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("requested_language", "interface_language", "expected"),
|
("language", "expected"),
|
||||||
[
|
[
|
||||||
("en-US", "fr-FR", "en-US"),
|
("fr-FR", "fr-FR"),
|
||||||
("invalid", "fr-FR", "fr-FR"),
|
("invalid", "en-US"),
|
||||||
(None, "custom-language", "custom-language"),
|
|
||||||
(None, None, languages[0]),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_list_recommended_resolves_language(
|
def test_list_recommended_resolves_language(
|
||||||
requested_language: str | None,
|
language: str,
|
||||||
interface_language: str | None,
|
|
||||||
expected: str,
|
expected: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
catalog = MagicMock()
|
catalog = MagicMock()
|
||||||
@ -101,8 +97,7 @@ def test_list_recommended_resolves_language(
|
|||||||
service, _ = _service(catalog=catalog)
|
service, _ = _service(catalog=catalog)
|
||||||
|
|
||||||
service.list_recommended(
|
service.list_recommended(
|
||||||
requested_language=requested_language,
|
language=language,
|
||||||
interface_language=interface_language,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
catalog.list_recommended.assert_called_once_with(expected)
|
catalog.list_recommended.assert_called_once_with(expected)
|
||||||
@ -113,7 +108,7 @@ def test_list_recommended_disables_upstream_trial_without_querying_trial_apps()
|
|||||||
catalog.list_recommended.return_value = _page("app-1")
|
catalog.list_recommended.return_value = _page("app-1")
|
||||||
service, trial_apps = _service(catalog=catalog)
|
service, trial_apps = _service(catalog=catalog)
|
||||||
|
|
||||||
result = service.list_recommended(requested_language="en-US", interface_language=None)
|
result = service.list_recommended(language="en-US")
|
||||||
|
|
||||||
assert result.recommended_apps[0].can_trial is False
|
assert result.recommended_apps[0].can_trial is False
|
||||||
trial_apps.existing_ids.assert_not_called()
|
trial_apps.existing_ids.assert_not_called()
|
||||||
@ -130,7 +125,7 @@ def test_list_recommended_enriches_trial_status_in_one_bulk_query() -> None:
|
|||||||
trial_enabled=True,
|
trial_enabled=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
result = service.list_recommended(requested_language="en-US", interface_language=None)
|
result = service.list_recommended(language="en-US")
|
||||||
|
|
||||||
assert [app.can_trial for app in result.recommended_apps] == [True, False]
|
assert [app.can_trial for app in result.recommended_apps] == [True, False]
|
||||||
trial_apps.existing_ids.assert_called_once_with(["app-1", "app-2"])
|
trial_apps.existing_ids.assert_called_once_with(["app-1", "app-2"])
|
||||||
@ -141,9 +136,9 @@ def test_list_learn_dify_does_not_return_categories() -> None:
|
|||||||
catalog.list_learn_dify.return_value = _page(categories=("ignored",))
|
catalog.list_learn_dify.return_value = _page(categories=("ignored",))
|
||||||
service, _ = _service(catalog=catalog)
|
service, _ = _service(catalog=catalog)
|
||||||
|
|
||||||
result = service.list_learn_dify(requested_language="invalid", interface_language="fr-FR")
|
result = service.list_learn_dify(language="invalid")
|
||||||
|
|
||||||
catalog.list_learn_dify.assert_called_once_with("fr-FR")
|
catalog.list_learn_dify.assert_called_once_with("en-US")
|
||||||
assert result.recommended_apps == ()
|
assert result.recommended_apps == ()
|
||||||
assert not hasattr(result, "categories")
|
assert not hasattr(result, "categories")
|
||||||
|
|
||||||
|
|||||||
@ -137,7 +137,7 @@ export const zLearnDifyAppListResponseWritable = z.object({
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const zGetExploreAppsQuery = z.object({
|
export const zGetExploreAppsQuery = z.object({
|
||||||
language: z.string().optional(),
|
language: z.string().optional().default('en-US'),
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -146,7 +146,7 @@ export const zGetExploreAppsQuery = z.object({
|
|||||||
export const zGetExploreAppsResponse = zRecommendedAppListResponse
|
export const zGetExploreAppsResponse = zRecommendedAppListResponse
|
||||||
|
|
||||||
export const zGetExploreAppsLearnDifyQuery = z.object({
|
export const zGetExploreAppsLearnDifyQuery = z.object({
|
||||||
language: z.string().optional(),
|
language: z.string().optional().default('en-US'),
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user