fix: guard against None system_prompt in _ensure_persona_and_skills

ProviderRequest.system_prompt defaults to None. When a persona with a
prompt is configured, _ensure_persona_and_skills calls
``req.system_prompt += ...`` which crashes with ``TypeError`` when
system_prompt is None.

Added a None guard before the persona prompt injection and skills prompt
appending sections so they always operate on a string.
This commit is contained in:
LIghtJUNction
2026-04-29 07:37:04 +08:00
parent 6b36e1abac
commit e2139fd91b
2 changed files with 54 additions and 0 deletions

View File

@@ -399,6 +399,9 @@ async def _ensure_persona_and_skills(
event, extract_persona_custom_error_message_from_persona(persona)
)
if req.system_prompt is None:
req.system_prompt = ""
if persona:
# Inject persona system prompt
if prompt := persona["prompt"]:

View File

@@ -0,0 +1,51 @@
"""Test that _ensure_persona_and_skills handles None system_prompt.
When ProviderRequest.system_prompt is None (the default), calling
_ensure_persona_and_skills with a persona that has a prompt should
not crash with ``TypeError: unsupported operand type(s) for +=``.
The bug was that ``req.system_prompt += ...`` was called when
system_prompt was None instead of initializing it to "" first.
"""
import pytest
from unittest.mock import AsyncMock, MagicMock
@pytest.mark.asyncio
async def test_ensure_persona_and_skills_handles_none_system_prompt():
from astrbot.core.astr_main_agent import _ensure_persona_and_skills
from astrbot.core.provider.entities import ProviderRequest
from astrbot.core.db.po import ConversationV2
# ProviderRequest.system_prompt defaults to None
req = ProviderRequest()
req.conversation = ConversationV2(
conversation_id="test",
platform_id="test",
user_id="test",
)
cfg = {"computer_use_runtime": "local"}
plugin_context = MagicMock()
plugin_context.persona_manager.resolve_selected_persona = AsyncMock(
return_value=(
"persona-1",
{"prompt": "You are a helpful assistant.", "name": "test"},
None,
False,
)
)
event = MagicMock()
event.unified_msg_origin = "test:test_user"
# This should NOT raise TypeError even though req.system_prompt is None
try:
await _ensure_persona_and_skills(req, cfg, plugin_context, event)
except TypeError as e:
pytest.fail(f"_ensure_persona_and_skills crashed with TypeError: {e}")
assert req.system_prompt is not None
assert "# Persona Instructions" in req.system_prompt