Przeglądaj źródła

fix: 修复脚本 protagonist_state 格式兼容性问题

- status_reporter.py: 支持 allies/enemies 列表格式的关系数据
- update_state.py: 支持嵌套和平铺两种 power/location 格式
- context_manager.py: 添加 protagonist_state 双格式兼容

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
lingfengQAQ 5 miesięcy temu
rodzic
commit
a30486f904

+ 34 - 5
.claude/skills/webnovel-writer/scripts/context_manager.py

@@ -152,11 +152,36 @@ class ContextManager:
 
         protag_state = self.state.get("protagonist_state", {})
 
+        # 支持两种格式:嵌套格式和平铺格式
+        # power 字段
+        power_data = protag_state.get("power", {})
+        if isinstance(power_data, dict):
+            power = power_data
+        else:
+            # 平铺格式
+            power = {
+                "realm": protag_state.get("realm", "未知"),
+                "layer": protag_state.get("layer", 0),
+                "bottleneck": protag_state.get("bottleneck")
+            }
+
+        # location 字段
+        location_data = protag_state.get("location", {})
+        if isinstance(location_data, dict):
+            location = location_data.get("current", "未知")
+        else:
+            # 平铺格式 - location 是字符串
+            location = location_data if location_data else "未知"
+
+        # golden_finger 字段
+        gf_data = protag_state.get("golden_finger", {})
+        gf_name = gf_data.get("name", "无") if isinstance(gf_data, dict) else "无"
+
         brief = {
             "name": protag_state.get("name", "主角"),
-            "power": protag_state.get("power", {}),
-            "location": protag_state.get("location", {}).get("current", "未知"),
-            "golden_finger": protag_state.get("golden_finger", {}).get("name", "无")
+            "power": power,
+            "location": location,
+            "golden_finger": gf_name
         }
 
         # 读取主角卡的"核心性格"章节(如果存在)
@@ -205,9 +230,13 @@ class ContextManager:
                            characters: Optional[List[str]] = None) -> Dict[str, Any]:
         """构建场景上下文(1500 Token)"""
 
-        # 确定当前地点
+        # 确定当前地点(支持嵌套和平铺两种格式)
         if not location and self.state:
-            location = self.state.get("protagonist_state", {}).get("location", {}).get("current")
+            location_data = self.state.get("protagonist_state", {}).get("location", {})
+            if isinstance(location_data, dict):
+                location = location_data.get("current")
+            else:
+                location = location_data if location_data else None
 
         scene = {
             "location_details": self._get_location_details(location) if location else None,

+ 30 - 7
.claude/skills/webnovel-writer/scripts/status_reporter.py

@@ -492,15 +492,38 @@ class StatusReporter:
 
         lines = ["```mermaid", "graph LR"]
 
-        for char_name, rel_data in relationships.items():
-            affection = rel_data.get("affection", 0)
-            hatred = rel_data.get("hatred", 0)
+        # 支持两种格式:
+        # 格式1(新): {"allies": [...], "enemies": [...]}
+        # 格式2(旧): {"角色名": {"affection": X, "hatred": Y}}
+
+        allies = relationships.get("allies", [])
+        enemies = relationships.get("enemies", [])
+
+        if allies or enemies:
+            # 新格式
+            for ally in allies:
+                if isinstance(ally, dict):
+                    name = ally.get("name", "未知")
+                    relation = ally.get("relation", "友好")
+                    lines.append(f"    {protagonist_name} -->|{relation}| {name}")
+
+            for enemy in enemies:
+                if isinstance(enemy, dict):
+                    name = enemy.get("name", "未知")
+                    relation = enemy.get("relation", "敌对")
+                    lines.append(f"    {protagonist_name} -.->|{relation}| {name}")
+        else:
+            # 旧格式兼容
+            for char_name, rel_data in relationships.items():
+                if isinstance(rel_data, dict):
+                    affection = rel_data.get("affection", 0)
+                    hatred = rel_data.get("hatred", 0)
 
-            if affection > 0:
-                lines.append(f"    {protagonist_name} -->|好感度{affection}| {char_name}")
+                    if affection > 0:
+                        lines.append(f"    {protagonist_name} -->|好感度{affection}| {char_name}")
 
-            if hatred > 0:
-                lines.append(f"    {protagonist_name} -->|仇恨度{hatred}| {char_name}")
+                    if hatred > 0:
+                        lines.append(f"    {protagonist_name} -.->|仇恨度{hatred}| {char_name}")
 
         lines.append("```")
 

+ 39 - 15
.claude/skills/webnovel-writer/scripts/update_state.py

@@ -89,12 +89,19 @@ class StateUpdater:
                 print(f"❌ 缺少必需字段: {key}")
                 return False
 
-        # 验证嵌套结构
-        if "power" not in state["protagonist_state"]:
-            print(f"❌ 缺少 protagonist_state.power 字段")
+        # 验证嵌套结构(支持两种格式:嵌套和平铺)
+        ps = state["protagonist_state"]
+        # power 字段:支持 power.realm 或直接 realm
+        has_nested_power = "power" in ps and isinstance(ps.get("power"), dict)
+        has_flat_power = "realm" in ps
+        if not (has_nested_power or has_flat_power):
+            print(f"❌ 缺少 protagonist_state.power 或 protagonist_state.realm 字段")
             return False
 
-        if "location" not in state["protagonist_state"]:
+        # location 字段:支持 location.current 或直接 location
+        has_nested_location = isinstance(ps.get("location"), dict) and "current" in ps.get("location", {})
+        has_flat_location = isinstance(ps.get("location"), str)
+        if not (has_nested_location or has_flat_location):
             print(f"❌ 缺少 protagonist_state.location 字段")
             return False
 
@@ -165,20 +172,37 @@ class StateUpdater:
             return False
 
     def update_protagonist_power(self, realm: str, layer: int, bottleneck: str):
-        """更新主角实力"""
-        self.state["protagonist_state"]["power"] = {
-            "realm": realm,
-            "layer": layer,
-            "bottleneck": bottleneck
-        }
+        """更新主角实力(支持嵌套和平铺两种格式)"""
+        ps = self.state["protagonist_state"]
+        # 检测当前格式
+        if "power" in ps and isinstance(ps.get("power"), dict):
+            # 嵌套格式
+            ps["power"] = {
+                "realm": realm,
+                "layer": layer,
+                "bottleneck": bottleneck if bottleneck != "null" else None
+            }
+        else:
+            # 平铺格式
+            ps["realm"] = realm
+            ps["layer"] = layer
+            ps["bottleneck"] = bottleneck if bottleneck != "null" else None
         print(f"📝 更新主角实力: {realm} {layer}层, 瓶颈: {bottleneck}")
 
     def update_protagonist_location(self, location: str, chapter: int):
-        """更新主角位置"""
-        self.state["protagonist_state"]["location"] = {
-            "current": location,
-            "last_chapter": chapter
-        }
+        """更新主角位置(支持嵌套和平铺两种格式)"""
+        ps = self.state["protagonist_state"]
+        # 检测当前格式
+        if isinstance(ps.get("location"), dict):
+            # 嵌套格式
+            ps["location"] = {
+                "current": location,
+                "last_chapter": chapter
+            }
+        else:
+            # 平铺格式
+            ps["location"] = location
+            ps["location_since_chapter"] = chapter
         print(f"📝 更新主角位置: {location}(第{chapter}章)")
 
     def update_golden_finger(self, name: str, level: int, cooldown: int):