diff --git a/astrbot/core/agent/message.py b/astrbot/core/agent/message.py index 374ec7dca..6e3a4012d 100644 --- a/astrbot/core/agent/message.py +++ b/astrbot/core/agent/message.py @@ -3,7 +3,7 @@ from typing import Any, ClassVar, Literal, cast -from pydantic import BaseModel, GetCoreSchemaHandler +from pydantic import BaseModel, GetCoreSchemaHandler, model_validator from pydantic_core import core_schema @@ -145,23 +145,39 @@ class Message(BaseModel): "tool", ] - content: str | list[ContentPart] + content: str | list[ContentPart] | None = None """The content of the message.""" + tool_calls: list[ToolCall] | list[dict] | None = None + """The tool calls of the message.""" + + tool_call_id: str | None = None + """The ID of the tool call.""" + + @model_validator(mode="after") + def check_content_required(self): + # assistant + tool_calls is not None: allow content to be None + if self.role == "assistant" and self.tool_calls is not None: + return self + + # other all cases: content is required + if self.content is None: + raise ValueError( + "content is required unless role='assistant' and tool_calls is not None" + ) + return self + class AssistantMessageSegment(Message): """A message segment from the assistant.""" role: Literal["assistant"] = "assistant" - content: str | list[ContentPart] | None = None - tool_calls: list[ToolCall] | list[dict] | None = None class ToolCallMessageSegment(Message): """A message segment representing a tool call.""" role: Literal["tool"] = "tool" - tool_call_id: str class UserMessageSegment(Message):