Use POST for more-like-this flow

This commit is contained in:
-LAN- 2025-09-27 02:36:03 +08:00
parent 695d89ef2d
commit e0fb754e80
5 changed files with 243 additions and 12 deletions

View File

@ -108,7 +108,7 @@ class MessageFeedbackApi(InstalledAppResource):
endpoint="installed_app_more_like_this",
)
class MessageMoreLikeThisApi(InstalledAppResource):
def get(self, installed_app, message_id):
def post(self, installed_app, message_id):
app_model = installed_app.app
if app_model.mode != "completion":
raise NotCompletionAppError()
@ -117,7 +117,12 @@ class MessageMoreLikeThisApi(InstalledAppResource):
parser = reqparse.RequestParser()
parser.add_argument(
"response_mode", type=str, required=True, choices=["blocking", "streaming"], location="args"
"response_mode",
type=str,
required=False,
choices=["blocking", "streaming"],
default="blocking",
location="json",
)
args = parser.parse_args()

View File

@ -169,12 +169,6 @@ class MessageMoreLikeThisApi(WebApiResource):
@web_ns.doc(
params={
"message_id": {"description": "Message UUID", "type": "string", "required": True},
"response_mode": {
"description": "Response mode",
"type": "string",
"enum": ["blocking", "streaming"],
"required": True,
},
}
)
@web_ns.doc(
@ -187,7 +181,7 @@ class MessageMoreLikeThisApi(WebApiResource):
500: "Internal Server Error",
}
)
def get(self, app_model, end_user, message_id):
def post(self, app_model, end_user, message_id):
if app_model.mode != "completion":
raise NotCompletionAppError()
@ -195,7 +189,12 @@ class MessageMoreLikeThisApi(WebApiResource):
parser = reqparse.RequestParser()
parser.add_argument(
"response_mode", type=str, required=True, choices=["blocking", "streaming"], location="args"
"response_mode",
type=str,
required=False,
choices=["blocking", "streaming"],
default="blocking",
location="json",
)
args = parser.parse_args()

View File

@ -0,0 +1,124 @@
import inspect
import uuid
from types import SimpleNamespace
from unittest.mock import MagicMock
import pytest
from flask import Flask
from controllers.console.explore.error import NotCompletionAppError
from controllers.console.explore.message import MessageMoreLikeThisApi
from core.app.entities.app_invoke_entities import InvokeFrom
from models.account import Account
@pytest.fixture
def flask_app():
app = Flask(__name__)
app.config["TESTING"] = True
return app
@pytest.fixture
def account_user():
user = Account(name="Tester", email="tester@example.com")
user.id = "user-id"
return user
class TestConsoleExploreMessageMoreLikeThisApi:
def test_post_generates_with_blocking_default(self, flask_app, account_user, monkeypatch):
installed_app = SimpleNamespace(app=SimpleNamespace(mode="completion"))
response_payload = {"answer": "ok"}
generate_mock = MagicMock(return_value=object())
compact_mock = MagicMock(return_value=response_payload)
monkeypatch.setattr(
"controllers.console.explore.message.current_user",
account_user,
raising=False,
)
monkeypatch.setattr(
"controllers.console.explore.message.AppGenerateService.generate_more_like_this",
generate_mock,
raising=False,
)
monkeypatch.setattr(
"controllers.console.explore.message.helper.compact_generate_response",
compact_mock,
raising=False,
)
handler = inspect.unwrap(MessageMoreLikeThisApi.post)
controller = MessageMoreLikeThisApi()
message_id = uuid.uuid4()
with flask_app.test_request_context(
f"/messages/{message_id}/more-like-this",
method="POST",
json={},
):
result = handler(controller, installed_app, message_id)
assert result == response_payload
generate_mock.assert_called_once()
call_kwargs = generate_mock.call_args.kwargs
assert call_kwargs["streaming"] is False
assert call_kwargs["invoke_from"] == InvokeFrom.EXPLORE
assert call_kwargs["message_id"] == str(message_id)
compact_mock.assert_called_once_with(generate_mock.return_value)
def test_post_allows_streaming_mode(self, flask_app, account_user, monkeypatch):
installed_app = SimpleNamespace(app=SimpleNamespace(mode="completion"))
generate_mock = MagicMock(return_value=object())
monkeypatch.setattr(
"controllers.console.explore.message.current_user",
account_user,
raising=False,
)
monkeypatch.setattr(
"controllers.console.explore.message.AppGenerateService.generate_more_like_this",
generate_mock,
raising=False,
)
monkeypatch.setattr(
"controllers.console.explore.message.helper.compact_generate_response",
MagicMock(return_value={}),
raising=False,
)
handler = inspect.unwrap(MessageMoreLikeThisApi.post)
controller = MessageMoreLikeThisApi()
message_id = uuid.uuid4()
with flask_app.test_request_context(
f"/messages/{message_id}/more-like-this",
method="POST",
json={"response_mode": "streaming"},
):
handler(controller, installed_app, message_id)
generate_mock.assert_called_once()
assert generate_mock.call_args.kwargs["streaming"] is True
def test_non_completion_app_raises(self, flask_app, account_user, monkeypatch):
installed_app = SimpleNamespace(app=SimpleNamespace(mode="chat"))
monkeypatch.setattr(
"controllers.console.explore.message.current_user",
account_user,
raising=False,
)
handler = inspect.unwrap(MessageMoreLikeThisApi.post)
controller = MessageMoreLikeThisApi()
message_id = uuid.uuid4()
with flask_app.test_request_context(
f"/messages/{message_id}/more-like-this",
method="POST",
json={},
):
with pytest.raises(NotCompletionAppError):
handler(controller, installed_app, message_id)

View File

@ -0,0 +1,103 @@
import inspect
import uuid
from types import SimpleNamespace
from unittest.mock import MagicMock
import pytest
from flask import Flask
from controllers.web.error import NotCompletionAppError
from controllers.web.message import MessageMoreLikeThisApi
from core.app.entities.app_invoke_entities import InvokeFrom
@pytest.fixture
def flask_app():
app = Flask(__name__)
app.config["TESTING"] = True
return app
class TestWebMessageMoreLikeThisApi:
def test_post_uses_blocking_by_default(self, flask_app, monkeypatch):
app_model = SimpleNamespace(mode="completion")
end_user = SimpleNamespace()
response_payload = {"answer": "ok"}
generate_mock = MagicMock(return_value=object())
compact_mock = MagicMock(return_value=response_payload)
monkeypatch.setattr(
"controllers.web.message.AppGenerateService.generate_more_like_this",
generate_mock,
raising=False,
)
monkeypatch.setattr(
"controllers.web.message.helper.compact_generate_response",
compact_mock,
raising=False,
)
handler = inspect.unwrap(MessageMoreLikeThisApi.post)
controller = MessageMoreLikeThisApi()
message_id = uuid.uuid4()
with flask_app.test_request_context(
f"/messages/{message_id}/more-like-this",
method="POST",
json={},
):
result = handler(controller, app_model, end_user, message_id)
assert result == response_payload
generate_mock.assert_called_once()
call_kwargs = generate_mock.call_args.kwargs
assert call_kwargs["streaming"] is False
assert call_kwargs["invoke_from"] == InvokeFrom.WEB_APP
assert call_kwargs["message_id"] == str(message_id)
compact_mock.assert_called_once_with(generate_mock.return_value)
def test_post_allows_streaming_mode(self, flask_app, monkeypatch):
app_model = SimpleNamespace(mode="completion")
end_user = SimpleNamespace()
generate_mock = MagicMock(return_value=object())
monkeypatch.setattr(
"controllers.web.message.AppGenerateService.generate_more_like_this",
generate_mock,
raising=False,
)
monkeypatch.setattr(
"controllers.web.message.helper.compact_generate_response",
MagicMock(return_value={}),
raising=False,
)
handler = inspect.unwrap(MessageMoreLikeThisApi.post)
controller = MessageMoreLikeThisApi()
message_id = uuid.uuid4()
with flask_app.test_request_context(
f"/messages/{message_id}/more-like-this",
method="POST",
json={"response_mode": "streaming"},
):
handler(controller, app_model, end_user, message_id)
generate_mock.assert_called_once()
assert generate_mock.call_args.kwargs["streaming"] is True
def test_non_completion_app_raises(self, flask_app):
app_model = SimpleNamespace(mode="chat")
end_user = SimpleNamespace()
handler = inspect.unwrap(MessageMoreLikeThisApi.post)
controller = MessageMoreLikeThisApi()
message_id = uuid.uuid4()
with flask_app.test_request_context(
f"/messages/{message_id}/more-like-this",
method="POST",
json={},
):
with pytest.raises(NotCompletionAppError):
handler(controller, app_model, end_user, message_id)

View File

@ -251,8 +251,8 @@ export const updateFeedback = async ({ url, body }: { url: string; body: Feedbac
}
export const fetchMoreLikeThis = async (messageId: string, isInstalledApp: boolean, installedAppId = '') => {
return (getAction('get', isInstalledApp))(getUrl(`/messages/${messageId}/more-like-this`, isInstalledApp, installedAppId), {
params: {
return (getAction('post', isInstalledApp))(getUrl(`/messages/${messageId}/more-like-this`, isInstalledApp, installedAppId), {
body: {
response_mode: 'blocking',
},
})