修复: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

@@ -1,34 +1,31 @@
"""
Story 图片回填 — 将 asset:// 引用插入 markdown。
Story 图片回填 — 将 asset:// 引用追加到 markdown 末尾
图片生成成功后,基于 source_span 或 fallback 位置插入 ![caption](asset://asset_id)。
图片生成成功后,在正文最后插入 ![alt](asset://asset_id)。
alt 使用原始 prompt 短文prompt_brief而非模板拼接后的完整出图 prompt。
"""
def _escape_markdown_image_alt(text: str) -> str:
"""在 ![alt](...) 的 alt 中安全转义 \\ 与 ]。"""
return text.replace("\\", "\\\\").replace("]", "\\]")
def backfill_image_into_markdown(
markdown: str,
asset_id: str,
caption: str,
*,
source_span: dict | None = None,
image_alt: str,
) -> str:
"""
将图片引用回填到 markdown。
将图片引用追加到 markdown 末尾
格式:![caption](asset://asset_id)
位置:若 source_span 有效则在对应段落后插入;否则在开头插入
格式:![image_alt](asset://asset_id)
image_alt 一般为 intent.prompt_brief原始图片提示短文
"""
img_ref = f"![{caption}](asset://{asset_id})"
raw = (image_alt or "").strip() or "主插图"
alt = _escape_markdown_image_alt(raw)
img_ref = f"![{alt}](asset://{asset_id})"
if not markdown or not markdown.strip():
return img_ref
if source_span and isinstance(source_span, dict):
start = source_span.get("start")
end = source_span.get("end")
if start is not None and end is not None and 0 <= start <= end <= len(markdown):
return markdown[:end] + "\n\n" + img_ref + "\n\n" + markdown[end:]
parts = markdown.strip().split("\n\n", 1)
if len(parts) == 1:
return img_ref + "\n\n" + markdown.strip()
return parts[0] + "\n\n" + img_ref + "\n\n" + parts[1]
body = markdown.rstrip()
return f"{body}\n\n{img_ref}\n"