修复:CI 部署环境与 ref 错配、迁移碎片化、图片意图 source_span、章节物化脏版式、会话历史与本地语音不一致

新增:TTS 上传 COS 与分片、章节 reading_segments 物化与快照、markdown 清洗、会话消息 repository、语音 store 重构与相关测试
This commit is contained in:
Kevin
2026-03-20 16:36:42 +08:00
parent 7317bf10cd
commit 8af37e5e8e
65 changed files with 1704 additions and 504 deletions

View File

@@ -85,6 +85,7 @@ class RedisService:
message_type: str = "text",
voice_session_id: str | None = None,
timestamp: str | int | None = None,
audio_duration_seconds: int | None = None,
) -> bool:
try:
client = await self.get_client()
@@ -98,6 +99,12 @@ class RedisService:
}
if voice_session_id:
item["voiceSessionId"] = voice_session_id
if (
audio_duration_seconds is not None
and audio_duration_seconds > 0
and message_type == "audio"
):
item["durationSeconds"] = int(audio_duration_seconds)
history.append(item)
await client.setex(
key, self.session_ttl, json.dumps(history, ensure_ascii=False)
@@ -107,6 +114,41 @@ class RedisService:
logger.error("添加消息失败: %s", e)
return False
async def append_tts_audio_url_to_last_ai_message(
self, conversation_id: str, url: str
) -> bool:
"""向最近一条 AI 消息的 ttsAudioUrls 追加 COS 公开 URL。"""
if not url:
return False
try:
client = await self.get_client()
key = self._conversation_key(conversation_id)
history = await self.get_conversation_history(conversation_id)
for i in range(len(history) - 1, -1, -1):
if history[i].get("role") == "ai":
existing = history[i].get("ttsAudioUrls")
urls: List[str] = (
[x for x in existing if isinstance(x, str)]
if isinstance(existing, list)
else []
)
urls.append(url)
history[i]["ttsAudioUrls"] = urls
break
else:
logger.warning(
"append_tts_audio_url: no ai message in history conversation_id=%s",
conversation_id,
)
return False
await client.setex(
key, self.session_ttl, json.dumps(history, ensure_ascii=False)
)
return True
except Exception as e:
logger.error("append_tts_audio_url 失败: %s", e)
return False
async def clear_conversation_history(self, conversation_id: str) -> bool:
try:
client = await self.get_client()