From 3cd38480988cf25c3cfef593d9ba6fbef29e99a6 Mon Sep 17 00:00:00 2001 From: piexian <64474352+piexian@users.noreply.github.com> Date: Sun, 29 Mar 2026 03:44:03 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E8=87=AA=E5=AE=9A=E4=B9=89=E6=8A=A5=E9=94=99=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E5=8F=8D=E8=80=8C=E4=BC=9A=E6=BC=8F=E6=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/astr_agent_run_util.py | 1 + 1 file changed, 1 insertion(+) diff --git a/astrbot/core/astr_agent_run_util.py b/astrbot/core/astr_agent_run_util.py index eca24699ae..df458a55ec 100644 --- a/astrbot/core/astr_agent_run_util.py +++ b/astrbot/core/astr_agent_run_util.py @@ -270,6 +270,7 @@ async def run_agent( yield MessageChain().message(err_msg) else: astr_event.set_result(MessageEventResult().message(err_msg)) + yield return From 147b391d9d1819337d78973c66a160d38935f950 Mon Sep 17 00:00:00 2001 From: piexian <64474352+piexian@users.noreply.github.com> Date: Mon, 30 Mar 2026 02:46:04 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E6=8A=A5=E9=94=99=E6=96=87=E6=A1=88=E6=9C=AA?= =?UTF-8?q?=E8=A6=86=E7=9B=96=E6=89=80=E6=9C=89=E9=94=99=E8=AF=AF=E5=87=BA?= =?UTF-8?q?=E5=8F=A3=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agent/runners/tool_loop_agent_runner.py | 15 ++++++-------- astrbot/core/astr_agent_run_util.py | 20 ++++--------------- astrbot/core/persona_error_reply.py | 17 ++++++++++++++++ .../method/agent_sub_stages/internal.py | 12 ++++------- .../method/agent_sub_stages/third_party.py | 13 ++++-------- 5 files changed, 35 insertions(+), 42 deletions(-) diff --git a/astrbot/core/agent/runners/tool_loop_agent_runner.py b/astrbot/core/agent/runners/tool_loop_agent_runner.py index 3fb487cbe6..3ec3523809 100644 --- a/astrbot/core/agent/runners/tool_loop_agent_runner.py +++ b/astrbot/core/agent/runners/tool_loop_agent_runner.py @@ -33,7 +33,7 @@ MessageChain, ) from astrbot.core.persona_error_reply import ( - extract_persona_custom_error_message_from_event, + get_user_facing_error_message, ) from astrbot.core.provider.entities import ( LLMResponse, @@ -106,11 +106,6 @@ class ToolLoopAgentRunner(BaseAgentRunner[TContext]): EMPTY_OUTPUT_RETRY_WAIT_MIN_S = 1 EMPTY_OUTPUT_RETRY_WAIT_MAX_S = 4 - def _get_persona_custom_error_message(self) -> str | None: - """Read persona-level custom error message from event extras when available.""" - event = getattr(self.run_context.context, "event", None) - return extract_persona_custom_error_message_from_event(event) - async def _complete_with_assistant_response(self, llm_resp: LLMResponse) -> None: """Finalize the current step as a plain assistant response with no tool calls.""" self.final_llm_resp = llm_resp @@ -517,10 +512,12 @@ async def step(self): self.stats.end_time = time.time() self._transition_state(AgentState.ERROR) self._resolve_unconsumed_follow_ups() - custom_error_message = self._get_persona_custom_error_message() - error_text = custom_error_message or ( - f"LLM 响应错误: {llm_resp.completion_text or '未知错误'}" + logger.error( + "LLM responded with error role: %s", + llm_resp.completion_text or "unknown", ) + event = getattr(self.run_context.context, "event", None) + error_text = get_user_facing_error_message(event) yield AgentResponse( type="err", data=AgentResponseData( diff --git a/astrbot/core/astr_agent_run_util.py b/astrbot/core/astr_agent_run_util.py index df458a55ec..0ee6af9dc9 100644 --- a/astrbot/core/astr_agent_run_util.py +++ b/astrbot/core/astr_agent_run_util.py @@ -1,7 +1,6 @@ import asyncio import re import time -import traceback from collections.abc import AsyncGenerator from astrbot.core import logger @@ -15,7 +14,7 @@ ResultContentType, ) from astrbot.core.persona_error_reply import ( - extract_persona_custom_error_message_from_event, + get_user_facing_error_message, ) from astrbot.core.provider.entities import LLMResponse from astrbot.core.provider.provider import TTSProvider @@ -234,26 +233,15 @@ async def run_agent( break - except Exception as e: + except Exception: if "stop_watcher" in locals() and not stop_watcher.done(): stop_watcher.cancel() try: await stop_watcher except asyncio.CancelledError: pass - logger.error(traceback.format_exc()) - - custom_error_message = extract_persona_custom_error_message_from_event( - astr_event - ) - if custom_error_message: - err_msg = custom_error_message - else: - err_msg = ( - f"Error occurred during AI execution.\n" - f"Error Type: {type(e).__name__}\n" - f"Error Message: {str(e)}" - ) + logger.error("Error occurred during AI execution", exc_info=True) + err_msg = get_user_facing_error_message(astr_event) error_llm_response = LLMResponse( role="err", diff --git a/astrbot/core/persona_error_reply.py b/astrbot/core/persona_error_reply.py index 5a99e0918e..52daa3067c 100644 --- a/astrbot/core/persona_error_reply.py +++ b/astrbot/core/persona_error_reply.py @@ -4,6 +4,7 @@ from typing import Any PERSONA_CUSTOM_ERROR_MESSAGE_EXTRA_KEY = "persona_custom_error_message" +DEFAULT_USER_FACING_ERROR_MESSAGE = "处理请求时出现异常,请稍后再试。" def normalize_persona_custom_error_message(value: object) -> str | None: @@ -34,6 +35,22 @@ def extract_persona_custom_error_message_from_event(event: Any) -> str | None: return None +def get_user_facing_error_message( + event: Any, + fallback_message: object = DEFAULT_USER_FACING_ERROR_MESSAGE, +) -> str: + """Resolve the user-facing error message with persona override support.""" + custom_error_message = extract_persona_custom_error_message_from_event(event) + if custom_error_message: + return custom_error_message + + normalized_fallback = normalize_persona_custom_error_message(fallback_message) + if normalized_fallback: + return normalized_fallback + + return DEFAULT_USER_FACING_ERROR_MESSAGE + + def set_persona_custom_error_message_on_event( event: Any, message: object ) -> str | None: diff --git a/astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py b/astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py index fc83c02091..ce829e3655 100644 --- a/astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py +++ b/astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py @@ -21,6 +21,7 @@ ) from astrbot.core.persona_error_reply import ( extract_persona_custom_error_message_from_event, + get_user_facing_error_message, resolve_event_conversation_persona_id, resolve_persona_custom_error_message, set_persona_custom_error_message_on_event, @@ -418,14 +419,9 @@ async def process( if runner_registered and agent_runner is not None: unregister_active_runner(event.unified_msg_origin, agent_runner) - except Exception as e: - logger.error(f"Error occurred while processing agent: {e}") - custom_error_message = extract_persona_custom_error_message_from_event( - event - ) - error_text = custom_error_message or ( - f"Error occurred while processing agent request: {e}" - ) + except Exception: + logger.error("Error occurred while processing agent", exc_info=True) + error_text = get_user_facing_error_message(event) await event.send(MessageChain().message(error_text)) finally: if typing_requested: diff --git a/astrbot/core/pipeline/process_stage/method/agent_sub_stages/third_party.py b/astrbot/core/pipeline/process_stage/method/agent_sub_stages/third_party.py index 070ad7bdee..e1a0a774ee 100644 --- a/astrbot/core/pipeline/process_stage/method/agent_sub_stages/third_party.py +++ b/astrbot/core/pipeline/process_stage/method/agent_sub_stages/third_party.py @@ -24,6 +24,7 @@ ResultContentType, ) from astrbot.core.persona_error_reply import ( + get_user_facing_error_message, resolve_event_conversation_persona_id, resolve_persona_custom_error_message, set_persona_custom_error_message_on_event, @@ -79,15 +80,9 @@ async def run_third_party_agent( yield resp.data["chain"], False elif resp.type == "err": yield resp.data["chain"], True - except Exception as e: - logger.error(f"Third party agent runner error: {e}") - err_msg = custom_error_message - if not err_msg: - err_msg = ( - f"Error occurred during AI execution.\n" - f"Error Type: {type(e).__name__} (3rd party)\n" - f"Error Message: {str(e)}" - ) + except Exception: + logger.error("Third party agent runner error", exc_info=True) + err_msg = get_user_facing_error_message(None, custom_error_message) yield MessageChain().message(err_msg), True