fix(HEL-191): 补回问天解势知识文件兜底并消除 Failed to fetch
宿主机 data 挂载会遮盖镜像内 heaven_knowledge.json;增加不受挂载影响的 seed, 并将缺文件/坏 JSON 转为结构化中文错误,前端展示可读提示而非 Failed to fetch。 Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
co-authored by
Cursor
multica-agent
parent
8a5e78f022
commit
ef86b31f6b
@@ -2,12 +2,23 @@ from __future__ import annotations
|
||||
|
||||
import json
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from backend.bootstrap.config import APP_DIR
|
||||
|
||||
|
||||
KNOWLEDGE_FILE = APP_DIR / "data" / "heaven_knowledge.json"
|
||||
# Baked into the image outside the ./data bind mount so volume overlay cannot hide it.
|
||||
KNOWLEDGE_SEED_FILE = Path(__file__).resolve().parent / "assets" / "heaven_knowledge.json"
|
||||
|
||||
|
||||
class HeavenKnowledgeError(ValueError):
|
||||
"""Structured knowledge-file failure surfaced to HTTP as Chinese API errors."""
|
||||
|
||||
def __init__(self, message: str, *, code: str) -> None:
|
||||
super().__init__(message)
|
||||
self.error_code = code
|
||||
|
||||
|
||||
def prepare_heaven_context(mode: str, calculation: dict[str, Any]) -> dict[str, Any]:
|
||||
@@ -379,9 +390,49 @@ def _line_record(line: dict[str, Any]) -> dict[str, Any]:
|
||||
}
|
||||
|
||||
|
||||
def resolve_heaven_knowledge_path() -> Path:
|
||||
"""Prefer the persisted data-dir file; fall back to the image-baked seed."""
|
||||
if KNOWLEDGE_FILE.is_file():
|
||||
return KNOWLEDGE_FILE
|
||||
if KNOWLEDGE_SEED_FILE.is_file():
|
||||
return KNOWLEDGE_SEED_FILE
|
||||
raise HeavenKnowledgeError(
|
||||
"问天知识文件缺失:未找到 heaven_knowledge.json。"
|
||||
"请确认宿主机 data 目录或镜像内 seed 文件完整。",
|
||||
code="heaven_knowledge_missing",
|
||||
)
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def _knowledge_catalog() -> dict[str, Any]:
|
||||
payload = json.loads(KNOWLEDGE_FILE.read_text(encoding="utf-8"))
|
||||
path = resolve_heaven_knowledge_path()
|
||||
try:
|
||||
raw = path.read_text(encoding="utf-8")
|
||||
except OSError as exc:
|
||||
raise HeavenKnowledgeError(
|
||||
f"问天知识文件无法读取({path.name}):{exc.strerror or exc}",
|
||||
code="heaven_knowledge_missing",
|
||||
) from exc
|
||||
try:
|
||||
payload = json.loads(raw)
|
||||
except json.JSONDecodeError as exc:
|
||||
raise HeavenKnowledgeError(
|
||||
f"问天知识文件 JSON 损坏({path.name}),无法解析:"
|
||||
f"第 {exc.lineno} 行附近。",
|
||||
code="heaven_knowledge_invalid",
|
||||
) from exc
|
||||
if not isinstance(payload, dict):
|
||||
raise HeavenKnowledgeError(
|
||||
f"问天知识文件格式不正确({path.name}):根节点必须是对象。",
|
||||
code="heaven_knowledge_invalid",
|
||||
)
|
||||
if not payload.get("version") or not isinstance(payload.get("sources"), dict):
|
||||
raise ValueError("问天知识库格式不完整。")
|
||||
raise HeavenKnowledgeError(
|
||||
f"问天知识库格式不完整({path.name}):缺少 version 或 sources。",
|
||||
code="heaven_knowledge_invalid",
|
||||
)
|
||||
return payload
|
||||
|
||||
|
||||
def clear_heaven_knowledge_cache() -> None:
|
||||
_knowledge_catalog.cache_clear()
|
||||
|
||||
Reference in New Issue
Block a user