ref:调整文件位置和命名,结构更清晰

This commit is contained in:
SengokuCola
2025-07-06 18:47:08 +08:00
parent 498d72384f
commit 1de15bcc31
23 changed files with 227 additions and 354 deletions

View File

@@ -1,135 +0,0 @@
import time
import os
from typing import Optional, Dict, Any
from src.common.logger import get_logger
import json
logger = get_logger("hfc") # Logger Name Changed
log_dir = "log/log_cycle_debug/"
class CycleDetail:
"""循环信息记录类"""
def __init__(self, cycle_id: int):
self.cycle_id = cycle_id
self.prefix = ""
self.thinking_id = ""
self.start_time = time.time()
self.end_time: Optional[float] = None
self.timers: Dict[str, float] = {}
# 新字段
self.loop_observation_info: Dict[str, Any] = {}
self.loop_processor_info: Dict[str, Any] = {} # 前处理器信息
self.loop_plan_info: Dict[str, Any] = {}
self.loop_action_info: Dict[str, Any] = {}
def to_dict(self) -> Dict[str, Any]:
"""将循环信息转换为字典格式"""
def convert_to_serializable(obj, depth=0, seen=None):
if seen is None:
seen = set()
# 防止递归过深
if depth > 5: # 降低递归深度限制
return str(obj)
# 防止循环引用
obj_id = id(obj)
if obj_id in seen:
return str(obj)
seen.add(obj_id)
try:
if hasattr(obj, "to_dict"):
# 对于有to_dict方法的对象直接调用其to_dict方法
return obj.to_dict()
elif isinstance(obj, dict):
# 对于字典,只保留基本类型和可序列化的值
return {
k: convert_to_serializable(v, depth + 1, seen)
for k, v in obj.items()
if isinstance(k, (str, int, float, bool))
}
elif isinstance(obj, (list, tuple)):
# 对于列表和元组,只保留可序列化的元素
return [
convert_to_serializable(item, depth + 1, seen)
for item in obj
if not isinstance(item, (dict, list, tuple))
or isinstance(item, (str, int, float, bool, type(None)))
]
elif isinstance(obj, (str, int, float, bool, type(None))):
return obj
else:
return str(obj)
finally:
seen.remove(obj_id)
return {
"cycle_id": self.cycle_id,
"start_time": self.start_time,
"end_time": self.end_time,
"timers": self.timers,
"thinking_id": self.thinking_id,
"loop_observation_info": convert_to_serializable(self.loop_observation_info),
"loop_processor_info": convert_to_serializable(self.loop_processor_info),
"loop_plan_info": convert_to_serializable(self.loop_plan_info),
"loop_action_info": convert_to_serializable(self.loop_action_info),
}
def complete_cycle(self):
"""完成循环,记录结束时间"""
self.end_time = time.time()
# 处理 prefix只保留中英文字符和基本标点
if not self.prefix:
self.prefix = "group"
else:
# 只保留中文、英文字母、数字和基本标点
allowed_chars = set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_")
self.prefix = (
"".join(char for char in self.prefix if "\u4e00" <= char <= "\u9fff" or char in allowed_chars)
or "group"
)
# current_time_minute = time.strftime("%Y%m%d_%H%M", time.localtime())
# try:
# self.log_cycle_to_file(
# log_dir + self.prefix + f"/{current_time_minute}_cycle_" + str(self.cycle_id) + ".json"
# )
# except Exception as e:
# logger.warning(f"写入文件日志,可能是群名称包含非法字符: {e}")
def log_cycle_to_file(self, file_path: str):
"""将循环信息写入文件"""
# 如果目录不存在,则创建目
dir_name = os.path.dirname(file_path)
# 去除特殊字符,保留字母、数字、下划线、中划线和中文
dir_name = "".join(
char for char in dir_name if char.isalnum() or char in ["_", "-", "/"] or "\u4e00" <= char <= "\u9fff"
)
# print("dir_name:", dir_name)
if dir_name and not os.path.exists(dir_name):
os.makedirs(dir_name, exist_ok=True)
# 写入文件
file_path = os.path.join(dir_name, os.path.basename(file_path))
# print("file_path:", file_path)
with open(file_path, "a", encoding="utf-8") as f:
f.write(json.dumps(self.to_dict(), ensure_ascii=False) + "\n")
def set_thinking_id(self, thinking_id: str):
"""设置思考消息ID"""
self.thinking_id = thinking_id
def set_loop_info(self, loop_info: Dict[str, Any]):
"""设置循环信息"""
self.loop_observation_info = loop_info["loop_observation_info"]
self.loop_processor_info = loop_info["loop_processor_info"]
self.loop_plan_info = loop_info["loop_plan_info"]
self.loop_action_info = loop_info["loop_action_info"]

View File

@@ -9,17 +9,14 @@ from rich.traceback import install
from src.chat.utils.prompt_builder import global_prompt_manager
from src.common.logger import get_logger
from src.chat.utils.timer_calculator import Timer
from src.chat.heart_flow.observation.observation import Observation
from src.chat.focus_chat.heartFC_Cycleinfo import CycleDetail
from src.chat.focus_chat.observation.observation import Observation
from src.chat.focus_chat.info.info_base import InfoBase
from src.chat.focus_chat.info_processors.chattinginfo_processor import ChattingInfoProcessor
from src.chat.focus_chat.info_processors.working_memory_processor import WorkingMemoryProcessor
from src.chat.heart_flow.observation.hfcloop_observation import HFCloopObservation
from src.chat.heart_flow.observation.working_observation import WorkingMemoryObservation
from src.chat.heart_flow.observation.chatting_observation import ChattingObservation
from src.chat.heart_flow.observation.actions_observation import ActionObservation
from src.chat.focus_chat.memory_activator import MemoryActivator
from src.chat.focus_chat.observation.hfcloop_observation import HFCloopObservation
from src.chat.focus_chat.observation.working_observation import WorkingMemoryObservation
from src.chat.focus_chat.observation.chatting_observation import ChattingObservation
from src.chat.focus_chat.observation.actions_observation import ActionObservation
from src.chat.focus_chat.info_processors.base_processor import BaseProcessor
from src.chat.planner_actions.planner_focus import ActionPlanner
from src.chat.planner_actions.action_modifier import ActionModifier
@@ -28,6 +25,7 @@ from src.config.config import global_config
from src.chat.focus_chat.hfc_performance_logger import HFCPerformanceLogger
from src.chat.focus_chat.hfc_version_manager import get_hfc_version
from src.person_info.relationship_builder_manager import relationship_builder_manager
from src.chat.focus_chat.hfc_utils import CycleDetail
install(extra_lines=3)
@@ -76,8 +74,6 @@ class HeartFChatting:
self.chat_stream = get_chat_manager().get_stream(self.stream_id)
self.log_prefix = f"[{get_chat_manager().get_stream_name(self.stream_id) or self.stream_id}]"
self.memory_activator = MemoryActivator()
self.relationship_builder = relationship_builder_manager.get_or_create_builder(self.stream_id)
# 新增:消息计数器和疲惫阈值

View File

@@ -5,9 +5,143 @@ from src.chat.message_receive.chat_stream import ChatStream
from src.chat.message_receive.message import UserInfo
from src.common.logger import get_logger
import json
import time
import os
from typing import Optional, Dict, Any
from src.common.logger import get_logger
import json
logger = get_logger(__name__)
log_dir = "log/log_cycle_debug/"
class CycleDetail:
"""循环信息记录类"""
def __init__(self, cycle_id: int):
self.cycle_id = cycle_id
self.prefix = ""
self.thinking_id = ""
self.start_time = time.time()
self.end_time: Optional[float] = None
self.timers: Dict[str, float] = {}
# 新字段
self.loop_observation_info: Dict[str, Any] = {}
self.loop_processor_info: Dict[str, Any] = {} # 前处理器信息
self.loop_plan_info: Dict[str, Any] = {}
self.loop_action_info: Dict[str, Any] = {}
def to_dict(self) -> Dict[str, Any]:
"""将循环信息转换为字典格式"""
def convert_to_serializable(obj, depth=0, seen=None):
if seen is None:
seen = set()
# 防止递归过深
if depth > 5: # 降低递归深度限制
return str(obj)
# 防止循环引用
obj_id = id(obj)
if obj_id in seen:
return str(obj)
seen.add(obj_id)
try:
if hasattr(obj, "to_dict"):
# 对于有to_dict方法的对象直接调用其to_dict方法
return obj.to_dict()
elif isinstance(obj, dict):
# 对于字典,只保留基本类型和可序列化的值
return {
k: convert_to_serializable(v, depth + 1, seen)
for k, v in obj.items()
if isinstance(k, (str, int, float, bool))
}
elif isinstance(obj, (list, tuple)):
# 对于列表和元组,只保留可序列化的元素
return [
convert_to_serializable(item, depth + 1, seen)
for item in obj
if not isinstance(item, (dict, list, tuple))
or isinstance(item, (str, int, float, bool, type(None)))
]
elif isinstance(obj, (str, int, float, bool, type(None))):
return obj
else:
return str(obj)
finally:
seen.remove(obj_id)
return {
"cycle_id": self.cycle_id,
"start_time": self.start_time,
"end_time": self.end_time,
"timers": self.timers,
"thinking_id": self.thinking_id,
"loop_observation_info": convert_to_serializable(self.loop_observation_info),
"loop_processor_info": convert_to_serializable(self.loop_processor_info),
"loop_plan_info": convert_to_serializable(self.loop_plan_info),
"loop_action_info": convert_to_serializable(self.loop_action_info),
}
def complete_cycle(self):
"""完成循环,记录结束时间"""
self.end_time = time.time()
# 处理 prefix只保留中英文字符和基本标点
if not self.prefix:
self.prefix = "group"
else:
# 只保留中文、英文字母、数字和基本标点
allowed_chars = set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_")
self.prefix = (
"".join(char for char in self.prefix if "\u4e00" <= char <= "\u9fff" or char in allowed_chars)
or "group"
)
# current_time_minute = time.strftime("%Y%m%d_%H%M", time.localtime())
# try:
# self.log_cycle_to_file(
# log_dir + self.prefix + f"/{current_time_minute}_cycle_" + str(self.cycle_id) + ".json"
# )
# except Exception as e:
# logger.warning(f"写入文件日志,可能是群名称包含非法字符: {e}")
def log_cycle_to_file(self, file_path: str):
"""将循环信息写入文件"""
# 如果目录不存在,则创建目
dir_name = os.path.dirname(file_path)
# 去除特殊字符,保留字母、数字、下划线、中划线和中文
dir_name = "".join(
char for char in dir_name if char.isalnum() or char in ["_", "-", "/"] or "\u4e00" <= char <= "\u9fff"
)
# print("dir_name:", dir_name)
if dir_name and not os.path.exists(dir_name):
os.makedirs(dir_name, exist_ok=True)
# 写入文件
file_path = os.path.join(dir_name, os.path.basename(file_path))
# print("file_path:", file_path)
with open(file_path, "a", encoding="utf-8") as f:
f.write(json.dumps(self.to_dict(), ensure_ascii=False) + "\n")
def set_thinking_id(self, thinking_id: str):
"""设置思考消息ID"""
self.thinking_id = thinking_id
def set_loop_info(self, loop_info: Dict[str, Any]):
"""设置循环信息"""
self.loop_observation_info = loop_info["loop_observation_info"]
self.loop_processor_info = loop_info["loop_processor_info"]
self.loop_plan_info = loop_info["loop_plan_info"]
self.loop_action_info = loop_info["loop_action_info"]
async def create_empty_anchor_message(
platform: str, group_info: dict, chat_stream: ChatStream

View File

@@ -1,97 +0,0 @@
from typing import Dict, Optional
from dataclasses import dataclass
from .info_base import InfoBase
@dataclass
class ChatInfo(InfoBase):
"""聊天信息类
用于记录和管理聊天相关的信息包括聊天ID、名称和类型等。
继承自 InfoBase 类,使用字典存储具体数据。
Attributes:
type (str): 信息类型标识符,固定为 "chat"
Data Fields:
chat_id (str): 聊天的唯一标识符
chat_name (str): 聊天的名称
chat_type (str): 聊天的类型
"""
type: str = "chat"
def set_chat_id(self, chat_id: str) -> None:
"""设置聊天ID
Args:
chat_id (str): 聊天的唯一标识符
"""
self.data["chat_id"] = chat_id
def set_chat_name(self, chat_name: str) -> None:
"""设置聊天名称
Args:
chat_name (str): 聊天的名称
"""
self.data["chat_name"] = chat_name
def set_chat_type(self, chat_type: str) -> None:
"""设置聊天类型
Args:
chat_type (str): 聊天的类型
"""
self.data["chat_type"] = chat_type
def get_chat_id(self) -> Optional[str]:
"""获取聊天ID
Returns:
Optional[str]: 聊天的唯一标识符,如果未设置则返回 None
"""
return self.get_info("chat_id")
def get_chat_name(self) -> Optional[str]:
"""获取聊天名称
Returns:
Optional[str]: 聊天的名称,如果未设置则返回 None
"""
return self.get_info("chat_name")
def get_chat_type(self) -> Optional[str]:
"""获取聊天类型
Returns:
Optional[str]: 聊天的类型,如果未设置则返回 None
"""
return self.get_info("chat_type")
def get_type(self) -> str:
"""获取信息类型
Returns:
str: 当前信息对象的类型标识符
"""
return self.type
def get_data(self) -> Dict[str, str]:
"""获取所有信息数据
Returns:
Dict[str, str]: 包含所有信息数据的字典
"""
return self.data
def get_info(self, key: str) -> Optional[str]:
"""获取特定属性的信息
Args:
key: 要获取的属性键名
Returns:
Optional[str]: 属性值,如果键不存在则返回 None
"""
return self.data.get(key)

View File

@@ -1,7 +1,7 @@
from abc import ABC, abstractmethod
from typing import List, Any
from src.chat.focus_chat.info.info_base import InfoBase
from src.chat.heart_flow.observation.observation import Observation
from src.chat.focus_chat.observation.observation import Observation
from src.common.logger import get_logger
logger = get_logger("base_processor")

View File

@@ -1,10 +1,10 @@
from typing import List, Any
from src.chat.focus_chat.info.obs_info import ObsInfo
from src.chat.heart_flow.observation.observation import Observation
from src.chat.focus_chat.observation.observation import Observation
from src.chat.focus_chat.info.info_base import InfoBase
from .base_processor import BaseProcessor
from src.common.logger import get_logger
from src.chat.heart_flow.observation.chatting_observation import ChattingObservation
from src.chat.focus_chat.observation.chatting_observation import ChattingObservation
from datetime import datetime
from src.llm_models.utils_model import LLMRequest
from src.config.config import global_config

View File

@@ -1,5 +1,5 @@
from src.chat.heart_flow.observation.chatting_observation import ChattingObservation
from src.chat.heart_flow.observation.observation import Observation
from src.chat.focus_chat.observation.chatting_observation import ChattingObservation
from src.chat.focus_chat.observation.observation import Observation
from src.llm_models.utils_model import LLMRequest
from src.config.config import global_config
import time
@@ -9,7 +9,7 @@ from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.chat.message_receive.chat_stream import get_chat_manager
from .base_processor import BaseProcessor
from typing import List
from src.chat.heart_flow.observation.working_observation import WorkingMemoryObservation
from src.chat.focus_chat.observation.working_observation import WorkingMemoryObservation
from src.chat.focus_chat.working_memory.working_memory import WorkingMemory
from src.chat.focus_chat.info.info_base import InfoBase
from json_repair import repair_json

View File

@@ -8,9 +8,9 @@ from src.chat.utils.chat_message_builder import (
get_person_id_list,
)
from src.chat.utils.prompt_builder import global_prompt_manager, Prompt
from src.chat.heart_flow.observation.observation import Observation
from src.chat.focus_chat.observation.observation import Observation
from src.common.logger import get_logger
from src.chat.heart_flow.utils_chat import get_chat_type_and_target_info
from src.chat.utils.utils import get_chat_type_and_target_info
logger = get_logger("observation")

View File

@@ -2,7 +2,7 @@
# 外部世界可以是某个聊天 不同平台的聊天 也可以是任意媒体
from datetime import datetime
from src.common.logger import get_logger
from src.chat.focus_chat.heartFC_Cycleinfo import CycleDetail
from src.chat.focus_chat.hfc_utils import CycleDetail
from typing import List
# Import the new utility function

View File

@@ -7,7 +7,6 @@ class ChatState(enum.Enum):
NORMAL = "随便水群"
FOCUSED = "认真水群"
class ChatStateInfo:
def __init__(self):
self.chat_status: ChatState = ChatState.NORMAL

View File

@@ -1,5 +1,3 @@
from .observation.observation import Observation
from src.chat.heart_flow.observation.chatting_observation import ChattingObservation
import asyncio
import time
from typing import Optional, List, Dict, Tuple
@@ -10,7 +8,7 @@ from src.chat.message_receive.chat_stream import get_chat_manager
from src.chat.focus_chat.heartFC_chat import HeartFChatting
from src.chat.normal_chat.normal_chat import NormalChat
from src.chat.heart_flow.chat_state_info import ChatState, ChatStateInfo
from .utils_chat import get_chat_type_and_target_info
from src.chat.utils.utils import get_chat_type_and_target_info
from src.config.config import global_config
from rich.traceback import install
@@ -314,24 +312,6 @@ class SubHeartflow:
f"{log_prefix} 尝试将状态从 {current_state.value} 变为 {new_state.value},但未成功或未执行更改。"
)
def add_observation(self, observation: Observation):
for existing_obs in self.observations:
if existing_obs.observe_id == observation.observe_id:
return
self.observations.append(observation)
def remove_observation(self, observation: Observation):
if observation in self.observations:
self.observations.remove(observation)
def get_all_observations(self) -> list[Observation]:
return self.observations
def _get_primary_observation(self) -> Optional[ChattingObservation]:
if self.observations and isinstance(self.observations[0], ChattingObservation):
return self.observations[0]
logger.warning(f"SubHeartflow {self.subheartflow_id} 没有找到有效的 ChattingObservation")
return None
def get_normal_chat_last_speak_time(self) -> float:
if self.normal_chat_instance:

View File

@@ -1,73 +0,0 @@
from typing import Optional, Tuple, Dict
from src.common.logger import get_logger
from src.chat.message_receive.chat_stream import get_chat_manager
from src.person_info.person_info import PersonInfoManager, get_person_info_manager
logger = get_logger("heartflow_utils")
def get_chat_type_and_target_info(chat_id: str) -> Tuple[bool, Optional[Dict]]:
"""
获取聊天类型(是否群聊)和私聊对象信息。
Args:
chat_id: 聊天流ID
Returns:
Tuple[bool, Optional[Dict]]:
- bool: 是否为群聊 (True 是群聊, False 是私聊或未知)
- Optional[Dict]: 如果是私聊,包含对方信息的字典;否则为 None。
字典包含: platform, user_id, user_nickname, person_id, person_name
"""
is_group_chat = False # Default to private/unknown
chat_target_info = None
try:
chat_stream = get_chat_manager().get_stream(chat_id)
if chat_stream:
if chat_stream.group_info:
is_group_chat = True
chat_target_info = None # Explicitly None for group chat
elif chat_stream.user_info: # It's a private chat
is_group_chat = False
user_info = chat_stream.user_info
platform = chat_stream.platform
user_id = user_info.user_id
# Initialize target_info with basic info
target_info = {
"platform": platform,
"user_id": user_id,
"user_nickname": user_info.user_nickname,
"person_id": None,
"person_name": None,
}
# Try to fetch person info
try:
# Assume get_person_id is sync (as per original code), keep using to_thread
person_id = PersonInfoManager.get_person_id(platform, user_id)
person_name = None
if person_id:
# get_value is async, so await it directly
person_info_manager = get_person_info_manager()
person_name = person_info_manager.get_value_sync(person_id, "person_name")
target_info["person_id"] = person_id
target_info["person_name"] = person_name
except Exception as person_e:
logger.warning(
f"获取 person_id 或 person_name 时出错 for {platform}:{user_id} in utils: {person_e}"
)
chat_target_info = target_info
else:
logger.warning(f"无法获取 chat_stream for {chat_id} in utils")
# Keep defaults: is_group_chat=False, chat_target_info=None
except Exception as e:
logger.error(f"获取聊天类型和目标信息时出错 for {chat_id}: {e}", exc_info=True)
# Keep defaults on error
return is_group_chat, chat_target_info

View File

@@ -9,7 +9,7 @@ from src.chat.message_receive.message import MessageRecv
from src.experimental.only_message_process import MessageProcessor
from src.chat.message_receive.storage import MessageStorage
from src.experimental.PFC.pfc_manager import PFCManager
from src.chat.focus_chat.heartflow_message_processor import HeartFCMessageReceiver
from src.chat.heart_flow.heartflow_message_processor import HeartFCMessageReceiver
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.config.config import global_config
from src.plugin_system.core.component_registry import component_registry # 导入新插件系统

View File

@@ -21,7 +21,7 @@ import traceback
from src.chat.planner_actions.planner_normal import NormalChatPlanner
from src.chat.planner_actions.action_modifier import ActionModifier
from src.chat.heart_flow.utils_chat import get_chat_type_and_target_info
from src.chat.utils.utils import get_chat_type_and_target_info
from src.manager.mood_manager import mood_manager
willing_manager = get_willing_manager()

View File

@@ -1,8 +1,8 @@
from typing import List, Optional, Any, Dict
from src.chat.heart_flow.observation.observation import Observation
from src.chat.focus_chat.observation.observation import Observation
from src.common.logger import get_logger
from src.chat.heart_flow.observation.hfcloop_observation import HFCloopObservation
from src.chat.heart_flow.observation.chatting_observation import ChattingObservation
from src.chat.focus_chat.observation.hfcloop_observation import HFCloopObservation
from src.chat.focus_chat.observation.chatting_observation import ChattingObservation
from src.chat.message_receive.chat_stream import get_chat_manager
from src.config.config import global_config
from src.llm_models.utils_model import LLMRequest

View File

@@ -11,7 +11,7 @@ from src.common.logger import get_logger
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.chat.planner_actions.action_manager import ActionManager
from json_repair import repair_json
from src.chat.heart_flow.utils_chat import get_chat_type_and_target_info
from src.chat.utils.utils import get_chat_type_and_target_info
from datetime import datetime
logger = get_logger("planner")

View File

@@ -10,7 +10,7 @@ from src.llm_models.utils_model import LLMRequest
from src.config.config import global_config
from src.chat.utils.timer_calculator import Timer # <--- Import Timer
from src.chat.focus_chat.heartFC_sender import HeartFCSender
from src.chat.heart_flow.utils_chat import get_chat_type_and_target_info
from src.chat.utils.utils import get_chat_type_and_target_info
from src.chat.message_receive.chat_stream import ChatStream
from src.chat.focus_chat.hfc_utils import parse_thinking_id_to_timestamp
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
@@ -26,7 +26,7 @@ from src.person_info.person_info import get_person_info_manager
from datetime import datetime
import re
from src.chat.knowledge.knowledge_lib import qa_manager
from src.chat.focus_chat.memory_activator import MemoryActivator
from src.chat.memory_system.memory_activator import MemoryActivator
from src.tools.tool_executor import ToolExecutor
logger = get_logger("replyer")

View File

@@ -14,6 +14,9 @@ from src.llm_models.utils_model import LLMRequest
from .typo_generator import ChineseTypoGenerator
from ...config.config import global_config
from ...common.message_repository import find_messages, count_messages
from typing import Optional, Tuple, Dict
from src.chat.message_receive.chat_stream import get_chat_manager
from src.person_info.person_info import PersonInfoManager, get_person_info_manager
logger = get_logger("chat_utils")
@@ -638,3 +641,69 @@ def translate_timestamp_to_human_readable(timestamp: float, mode: str = "normal"
else: # mode = "lite" or unknown
# 只返回时分秒格式,喵~
return time.strftime("%H:%M:%S", time.localtime(timestamp))
def get_chat_type_and_target_info(chat_id: str) -> Tuple[bool, Optional[Dict]]:
"""
获取聊天类型(是否群聊)和私聊对象信息。
Args:
chat_id: 聊天流ID
Returns:
Tuple[bool, Optional[Dict]]:
- bool: 是否为群聊 (True 是群聊, False 是私聊或未知)
- Optional[Dict]: 如果是私聊,包含对方信息的字典;否则为 None。
字典包含: platform, user_id, user_nickname, person_id, person_name
"""
is_group_chat = False # Default to private/unknown
chat_target_info = None
try:
chat_stream = get_chat_manager().get_stream(chat_id)
if chat_stream:
if chat_stream.group_info:
is_group_chat = True
chat_target_info = None # Explicitly None for group chat
elif chat_stream.user_info: # It's a private chat
is_group_chat = False
user_info = chat_stream.user_info
platform = chat_stream.platform
user_id = user_info.user_id
# Initialize target_info with basic info
target_info = {
"platform": platform,
"user_id": user_id,
"user_nickname": user_info.user_nickname,
"person_id": None,
"person_name": None,
}
# Try to fetch person info
try:
# Assume get_person_id is sync (as per original code), keep using to_thread
person_id = PersonInfoManager.get_person_id(platform, user_id)
person_name = None
if person_id:
# get_value is async, so await it directly
person_info_manager = get_person_info_manager()
person_name = person_info_manager.get_value_sync(person_id, "person_name")
target_info["person_id"] = person_id
target_info["person_name"] = person_name
except Exception as person_e:
logger.warning(
f"获取 person_id 或 person_name 时出错 for {platform}:{user_id} in utils: {person_e}"
)
chat_target_info = target_info
else:
logger.warning(f"无法获取 chat_stream for {chat_id} in utils")
# Keep defaults: is_group_chat=False, chat_target_info=None
except Exception as e:
logger.error(f"获取聊天类型和目标信息时出错 for {chat_id}: {e}", exc_info=True)
# Keep defaults on error
return is_group_chat, chat_target_info