fix(tier2): bootstrap /chat input.content 须为内容块列表(控制面 smoke 实证)

credential/agent/session 已通后,POST /chat/ 返 422:body.input.content「Input should be a
valid list」。根因 = Msg.content 经 REST 传 JSON 必须是内容块列表,而 bootstrap 发了裸字符串
(Python 端 UserMsg(content=str) 的字符串自动包块只在构造器内发生,不经 REST JSON 校验那条)。

修:加 _user_input(text) helper 统一组 input = {name,role,content:[TextBlock]},三处 chat
调用(start_new_game/resume_session/iterate_existing_project)改用它。TextBlock JSON 形状
{type:"text",text:...} 据源码 message/_block.py:11 核实。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
zizi 2026-06-24 07:57:39 +00:00
parent 295f232d20
commit 76aab8d703

View File

@ -48,6 +48,17 @@ WRITER_KICK_TEXT = (
)
def _user_input(text: str) -> dict[str, Any]:
"""组装 POST /chat/ 的 input(一条 user Msg)。
ChatRequest.input agentscope.message.Msg;Msg.content 必须是内容块列表而非裸字符串
(2026-06-24 活服务 smoke 实证:发裸字符串 content 422Input should be a valid list
Python UserMsg(content=str) 的字符串自动包块只发生在构造器内, REST JSON 不走那条,
故须显式发 [TextBlock])TextBlock JSON 形状 = {type:"text", text:...}(源码 message/_block.py:11)
"""
return {"name": "user", "role": "user", "content": [{"type": "text", "text": text}]}
def _resolve_m3_credential_payload(model_name: str = "MiniMax-M3") -> dict[str, Any]:
"""组装注册 M3 凭据(POST /credential/)的请求体——base_url/key 经 worker.client 解析,绝不硬编码。
@ -163,7 +174,7 @@ async def start_new_game(
chat_body = {
"agent_id": agent_id,
"session_id": session_id,
"input": {"name": "user", "role": "user", "content": WRITER_KICK_TEXT},
"input": _user_input(WRITER_KICK_TEXT),
}
chat = await _post(http, base_url, "/chat/", chat_body, user_header=user_id)
@ -197,7 +208,7 @@ async def resume_session(
chat_body = {
"agent_id": agent_id,
"session_id": session_id,
"input": {"name": "user", "role": "user", "content": text},
"input": _user_input(text),
}
async with httpx.AsyncClient() as http:
chat = await _post(http, base_url, "/chat/", chat_body, user_header=user_id)
@ -259,7 +270,7 @@ async def iterate_existing_project(
chat_body = {
"agent_id": agent_id,
"session_id": session_id,
"input": {"name": "user", "role": "user", "content": text},
"input": _user_input(text),
}
chat = await _post(http, base_url, "/chat/", chat_body, user_header=user_id)