mirror of
https://github.com/agent0ai/agent-zero.git
synced 2026-10-25 23:59:43 +00:00
Every send paid a blocking model_config_get round-trip before dispatching, because the frontend had to know whether a chat model is configured to decide between sending and rendering the setup card. Move the check behind the dispatch: a user_message_ui extension in _model_config flags unconfigured chats, the message handlers reject before logging or dispatching and return a model_not_configured payload, and the client opens the setup gate from that response. Isolated sends no longer make any configuration round-trip, the optimistic user row and draft handling stay intact through the gate flow, and the post-setup retry drops its bypass flag since the backend re-checks on dispatch. Validation: pytest tests/test_model_gate_backend_reject.py tests/test_welcome_composer_static.py tests/test_webui_chat_deletion.py tests/test_webui_send_pause_responsiveness_static.py tests/test_message_action_buttons_static.py tests/test_markdown_tilde_rendering.py tests/test_webui_message_queue_static.py (23 passed); node --check webui/index.js webui/components/chat/model-gate-store.js
79 lines
3.2 KiB
Python
79 lines
3.2 KiB
Python
from agent import AgentContext, UserMessage
|
|
from helpers.api import ApiHandler, Request, Response
|
|
|
|
from helpers import files, extension, message_queue as mq
|
|
import os
|
|
from helpers.security import safe_filename
|
|
from helpers.defer import DeferredTask
|
|
|
|
|
|
class Message(ApiHandler):
|
|
async def process(self, input: dict, request: Request) -> dict | Response:
|
|
task, context = await self.communicate(input=input, request=request)
|
|
return await self.respond(task, context)
|
|
|
|
async def respond(self, task: DeferredTask, context: AgentContext):
|
|
if task is None:
|
|
return {
|
|
"message": "Model not configured.",
|
|
"model_not_configured": True,
|
|
"context": context.id,
|
|
}
|
|
result = await task.result() # type: ignore
|
|
return {
|
|
"message": result,
|
|
"context": context.id,
|
|
}
|
|
|
|
async def communicate(self, input: dict, request: Request):
|
|
# Handle both JSON and multipart/form-data
|
|
if request.content_type.startswith("multipart/form-data"):
|
|
text = request.form.get("text", "")
|
|
ctxid = request.form.get("context", "")
|
|
message_id = request.form.get("message_id", None)
|
|
attachments = request.files.getlist("attachments")
|
|
attachment_paths = []
|
|
|
|
upload_folder_int = "/a0/usr/uploads"
|
|
upload_folder_ext = files.get_abs_path("usr/uploads") # for development environment
|
|
|
|
if attachments:
|
|
os.makedirs(upload_folder_ext, exist_ok=True)
|
|
for attachment in attachments:
|
|
if attachment.filename is None:
|
|
continue
|
|
filename = safe_filename(attachment.filename)
|
|
if not filename:
|
|
continue
|
|
save_path = files.get_abs_path(upload_folder_ext, filename)
|
|
attachment.save(save_path)
|
|
attachment_paths.append(os.path.join(upload_folder_int, filename))
|
|
else:
|
|
# Handle JSON request as before
|
|
input_data = request.get_json()
|
|
text = input_data.get("text", "")
|
|
ctxid = input_data.get("context", "")
|
|
message_id = input_data.get("message_id", None)
|
|
attachment_paths = []
|
|
|
|
# Now process the message
|
|
message = text
|
|
|
|
# Obtain agent context
|
|
context = self.use_context(ctxid)
|
|
|
|
# call extension point, alow it to modify data
|
|
data = { "message": message, "attachment_paths": attachment_paths }
|
|
await extension.call_extensions_async("user_message_ui", agent=context.get_agent(), data=data)
|
|
message = data.get("message", "")
|
|
attachment_paths = data.get("attachment_paths", [])
|
|
if data.get("model_not_configured"):
|
|
return None, context
|
|
|
|
# Store attachments in agent data
|
|
# context.agent0.set_data("attachments", attachment_paths)
|
|
|
|
# Log to console and UI using helper function
|
|
mq.log_user_message(context, message, attachment_paths, message_id)
|
|
|
|
return context.communicate(UserMessage(message=message, attachments=attachment_paths, id=message_id or "")), context
|