feat:移除旧的maisaka cli逻辑

This commit is contained in:
SengokuCola
2026-04-03 15:31:44 +08:00
parent 8ba43bb694
commit b74b60cb1a
8 changed files with 226 additions and 469 deletions

View File

@@ -14,6 +14,7 @@ from src.core.tooling import ToolExecutionResult
from ..context_messages import SessionBackedMessage
from ..message_adapter import format_speaker_content
from ..planner_message_utils import build_planner_prefix, build_session_backed_text_message
if TYPE_CHECKING:
from ..reasoning_engine import MaisakaReasoningEngine
@@ -141,20 +142,9 @@ class BuiltinToolRuntimeContext:
bot_name = global_config.bot.nickname.strip() or "MaiSaka"
reply_timestamp = datetime.now()
planner_prefix = (
f"[时间]{reply_timestamp.strftime('%H:%M:%S')}\n"
f"[用户]{bot_name}\n"
"[用户群昵称]\n"
"[msg_id]\n"
"[发言内容]"
)
history_message = SessionBackedMessage(
raw_message=MessageSequence([TextComponent(f"{planner_prefix}{reply_text}")]),
visible_text=format_speaker_content(
bot_name,
reply_text,
reply_timestamp,
),
history_message = build_session_backed_text_message(
speaker_name=bot_name,
text=reply_text,
timestamp=reply_timestamp,
source_kind="guided_reply",
)
@@ -170,12 +160,9 @@ class BuiltinToolRuntimeContext:
bot_name = global_config.bot.nickname.strip() or "MaiSaka"
reply_timestamp = datetime.now()
planner_prefix = (
f"[时间]{reply_timestamp.strftime('%H:%M:%S')}\n"
f"[用户]{bot_name}\n"
"[用户群昵称]\n"
"[msg_id]\n"
"[发言内容]"
planner_prefix = build_planner_prefix(
timestamp=reply_timestamp,
user_name=bot_name,
)
history_message = SessionBackedMessage(
raw_message=MessageSequence(

View File

@@ -3,6 +3,7 @@
from typing import Optional
from src.chat.replyer.replyer_manager import replyer_manager
from src.cli.maisaka_cli_sender import CLI_PLATFORM_NAME, render_cli_message
from src.common.logger import get_logger
from src.core.tooling import ToolExecutionContext, ToolExecutionResult, ToolInvocation, ToolSpec
from src.services import send_service
@@ -134,17 +135,22 @@ async def handle_tool(
combined_reply_text = "".join(reply_segments)
try:
sent = False
for index, segment in enumerate(reply_segments):
sent = await send_service.text_to_stream(
text=segment,
stream_id=tool_ctx.runtime.session_id,
set_reply=quote_reply if index == 0 else False,
reply_message=target_message if quote_reply and index == 0 else None,
selected_expressions=reply_result.selected_expression_ids or None,
typing=index > 0,
)
if not sent:
break
if tool_ctx.runtime.chat_stream.platform == CLI_PLATFORM_NAME:
for segment in reply_segments:
render_cli_message(segment)
sent = True
else:
for index, segment in enumerate(reply_segments):
sent = await send_service.text_to_stream(
text=segment,
stream_id=tool_ctx.runtime.session_id,
set_reply=quote_reply if index == 0 else False,
reply_message=target_message if quote_reply and index == 0 else None,
selected_expressions=reply_result.selected_expression_ids or None,
typing=index > 0,
)
if not sent:
break
except Exception:
logger.exception(
f"{tool_ctx.runtime.log_prefix} 发送文字消息时发生异常,目标消息编号={target_message_id}"

View File

@@ -40,6 +40,7 @@ from src.services.llm_service import LLMServiceClient
from .builtin_tool import get_builtin_tools
from .context_messages import AssistantMessage, LLMContextMessage, SessionBackedMessage, ToolResultMessage
from .message_adapter import format_speaker_content
from .planner_message_utils import build_session_backed_text_message
from .prompt_cli_renderer import PromptCLIVisualizer
@@ -920,37 +921,4 @@ class MaisakaChatLoopService:
if first_valid_index == 0:
return selected_history
return selected_history[first_valid_index:]
@staticmethod
def build_chat_context(user_text: str) -> List[LLMContextMessage]:
"""根据用户输入构造最小对话上下文。
Args:
user_text: 用户输入文本。
Returns:
List[LLMContextMessage]: 构造好的上下文消息列表。
"""
timestamp = datetime.now()
visible_text = format_speaker_content(
global_config.maisaka.user_name.strip() or "用户",
user_text,
timestamp,
)
planner_prefix = (
f"[时间]{timestamp.strftime('%H:%M:%S')}\n"
f"[用户]{global_config.maisaka.user_name.strip() or '用户'}\n"
"[用户群昵称]\n"
"[msg_id]\n"
"[发言内容]"
)
return [
SessionBackedMessage(
raw_message=MessageSequence([TextComponent(f"{planner_prefix}{user_text}")]),
visible_text=visible_text,
timestamp=timestamp,
source_kind="user",
)
]
return selected_history[first_valid_index:]

View File

@@ -0,0 +1,109 @@
"""Maisaka 规划器消息构造工具。"""
from datetime import datetime
from typing import Optional
from src.chat.message_receive.message import SessionMessage
from src.common.data_models.message_component_data_model import MessageSequence, TextComponent
from .context_messages import SessionBackedMessage
from .message_adapter import format_speaker_content
def build_planner_prefix(
*,
timestamp: datetime,
user_name: str,
group_card: str = "",
message_id: Optional[str] = None,
include_message_id: bool = True,
) -> str:
"""构造 Maisaka 规划器使用的统一消息前缀。
Args:
timestamp: 消息时间。
user_name: 展示给规划器的用户名。
group_card: 群昵称。
message_id: 消息 ID。
include_message_id: 是否输出 `msg_id` 段。
Returns:
str: 拼接完成的规划器前缀。
"""
prefix_parts = [
f"[时间]{timestamp.strftime('%H:%M:%S')}\n",
f"[用户名]{user_name}\n",
f"[用户群昵称]{group_card}\n",
]
if include_message_id:
prefix_parts.append(f"[msg_id]{message_id or ''}\n")
prefix_parts.append("[发言内容]")
return "".join(prefix_parts)
def build_planner_user_prefix_from_session_message(message: SessionMessage) -> str:
"""根据真实会话消息构造规划器前缀。
Args:
message: 原始会话消息。
Returns:
str: 规划器前缀字符串。
"""
user_info = message.message_info.user_info
user_name = user_info.user_nickname or user_info.user_id
return build_planner_prefix(
timestamp=message.timestamp,
user_name=user_name,
group_card=user_info.user_cardname or "",
message_id=message.message_id,
include_message_id=not message.is_notify and bool(message.message_id),
)
def build_session_backed_text_message(
*,
speaker_name: str,
text: str,
timestamp: datetime,
source_kind: str,
group_card: str = "",
message_id: Optional[str] = None,
include_message_id: bool = True,
) -> SessionBackedMessage:
"""构造带规划器前缀的纯文本历史消息。
Args:
speaker_name: 发言者名称。
text: 发言内容。
timestamp: 发言时间。
source_kind: 上下文来源类型。
group_card: 群昵称。
message_id: 消息 ID。
include_message_id: 是否输出 `msg_id` 段。
Returns:
SessionBackedMessage: 可直接写入历史的上下文消息。
"""
planner_prefix = build_planner_prefix(
timestamp=timestamp,
user_name=speaker_name,
group_card=group_card,
message_id=message_id,
include_message_id=include_message_id,
)
return SessionBackedMessage(
raw_message=MessageSequence([TextComponent(f"{planner_prefix}{text}")]),
visible_text=format_speaker_content(
speaker_name,
text,
timestamp,
message_id if include_message_id else None,
),
timestamp=timestamp,
message_id=message_id,
source_kind=source_kind,
)

View File

@@ -33,6 +33,7 @@ from .message_adapter import (
clone_message_sequence,
format_speaker_content,
)
from .planner_message_utils import build_planner_user_prefix_from_session_message
if TYPE_CHECKING:
from .runtime import MaisakaHeartFlowChatting
@@ -226,7 +227,7 @@ class MaisakaReasoningEngine:
async def _build_message_sequence(self, message: SessionMessage) -> tuple[MessageSequence, str]:
message_sequence = MessageSequence([])
planner_prefix = self._build_planner_user_prefix(message)
planner_prefix = build_planner_user_prefix_from_session_message(message)
appended_component = False
if global_config.maisaka.direct_image_input:
@@ -255,22 +256,6 @@ class MaisakaReasoningEngine:
return message_sequence, legacy_visible_text
@staticmethod
def _build_planner_user_prefix(message: SessionMessage) -> str:
user_info = message.message_info.user_info
timestamp_text = message.timestamp.strftime("%H:%M:%S")
user_name = user_info.user_nickname or user_info.user_id
group_card = user_info.user_cardname or ""
prefix_parts = [
f"[时间]{timestamp_text}\n",
f"[用户]{user_name}\n",
f"[用户群昵称]{group_card}\n",
]
if not message.is_notify and message.message_id:
prefix_parts.append(f"[msg_id]{message.message_id}\n")
prefix_parts.append("[发言内容]")
return "".join(prefix_parts)
def _build_legacy_visible_text(self, message: SessionMessage, source_sequence: MessageSequence) -> str:
user_info = message.message_info.user_info
speaker_name = user_info.user_cardname or user_info.user_nickname or user_info.user_id