diff --git a/yuthon_ai_agent/security/ai_security.xml b/yuthon_ai_agent/security/ai_security.xml index afebb493e..e40d83d2b 100644 --- a/yuthon_ai_agent/security/ai_security.xml +++ b/yuthon_ai_agent/security/ai_security.xml @@ -64,4 +64,51 @@ + + + + + + AI 对话:管理员可见全部 + + [(1,'=',1)] + + + + + + + + + AI 画像:管理员可见全部 + + [(1,'=',1)] + + + + + + + + + AI 记忆:管理员可见全部 + + [(1,'=',1)] + + + + + + + + + Token 用量:管理员可见全部 + + [(1,'=',1)] + + + + + + diff --git a/yuthon_wechat/controllers/ai_callback.py b/yuthon_wechat/controllers/ai_callback.py index 608a7c86f..f9d01f0c9 100644 --- a/yuthon_wechat/controllers/ai_callback.py +++ b/yuthon_wechat/controllers/ai_callback.py @@ -8,7 +8,7 @@ import logging import threading from odoo import http, api, SUPERUSER_ID -from odoo.http import request +from odoo.http import request, Response from ..utils.wx_biz_msg_crypt import WXBizMsgCrypt, WXBizMsgCryptError, parse_wecom_message @@ -53,11 +53,11 @@ class WecomAiCallback(http.Controller): wecom_app = self._get_ai_app_config() if not wecom_app: _logger.error("未找到 AI 回调应用配置(wecom_apps_type=ai_callback, category=agent)") - return "config error" + return Response("config error", content_type='text/plain') crypt = self._get_crypt_instance(wecom_app) if not crypt: - return "config error" + return Response("config error", content_type='text/plain') # === GET: URL验证 === if request.httprequest.method == 'GET': @@ -69,26 +69,27 @@ class WecomAiCallback(http.Controller): def _handle_verify(self, crypt, msg_signature, timestamp, nonce, echostr): """处理URL验证请求""" if not all([msg_signature, timestamp, nonce, echostr]): - _logger.warning("AI回调URL验证缺少参数") - return "param error" + _logger.warning("AI回调URL验证缺少参数: sig=%s, ts=%s, nonce=%s, echo=%s", + msg_signature, timestamp, nonce, bool(echostr)) + return Response("param error", content_type='text/plain') try: echo_plain = crypt.verify_url(msg_signature, timestamp, nonce, echostr) _logger.info("企业微信 AI 回调URL验证成功") - return echo_plain + return Response(echo_plain, content_type='text/plain') except WXBizMsgCryptError as e: _logger.error("AI回调URL验证失败: %s", e) - return "verify error" + return Response("verify error", content_type='text/plain') def _handle_message(self, crypt, msg_signature, timestamp, nonce): """处理接收消息请求""" if not all([msg_signature, timestamp, nonce]): _logger.warning("AI回调消息缺少签名参数") - return "" + return Response("", content_type='text/plain') post_data = request.httprequest.get_data(as_text=True) if not post_data: _logger.warning("AI回调消息体为空") - return "" + return Response("", content_type='text/plain') # 解密消息 try: @@ -110,12 +111,12 @@ class WecomAiCallback(http.Controller): # 只处理文本消息 if msg.get('msg_type') != 'text': _logger.info("AI回调收到非文本消息类型: %s,暂不处理", msg.get('msg_type')) - return "" + return Response("", content_type='text/plain') wecom_userid = msg.get('from_user') content = msg.get('content', '').strip() if not wecom_userid or not content: - return "" + return Response("", content_type='text/plain') # 异步处理: 立即返回空响应,后台线程处理AI对话并推送回复 db_name = request.env.cr.dbname @@ -126,7 +127,7 @@ class WecomAiCallback(http.Controller): ).start() # 立即返回空字符串,表示成功接收 - return "" + return Response("", content_type='text/plain') def _async_process_ai_message(self, db_name, wecom_userid, content): """