From 1ff34057550697bdfc87b029cec4c8c054754296 Mon Sep 17 00:00:00 2001 From: OG T Date: Sat, 18 Apr 2026 01:08:32 +0800 Subject: [PATCH] =?UTF-8?q?fix(drift-narrator):=20=E4=BF=AE=E5=BE=A9=20JSO?= =?UTF-8?q?N=20=E8=A3=B8=E5=A5=94=20=E2=80=94=20=E5=BE=9E=20NEMOTRON=20?= =?UTF-8?q?=E5=9B=9E=E5=82=B3=E8=A7=A3=E6=9E=90=20description=20=E6=AC=84?= =?UTF-8?q?=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因:openclaw.call() 經 NEMOTRON 路由後強制輸出 JSON(NEMOTRON_SYSTEM_PROMPT 鐵律) 但 _generate_narrative 期待純文字 → JSON 整包吐到 Telegram
 區塊裸奔

修復:收到 text 後先嘗試 JSON 解析
      - 成功 → 按優先順序取 description / action_title / reasoning
      - 失敗(非 JSON)→ 原文使用(向下相容 Ollama qwen 純文字回傳)

效果:Telegram Config Drift 卡片顯示繁中人話摘要,不再吐原始 JSON

2026-04-17 ogt + Claude Sonnet 4.6

Co-Authored-By: Claude Sonnet 4.6 
---
 .../src/services/drift_narrator_service.py    | 20 ++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/apps/api/src/services/drift_narrator_service.py b/apps/api/src/services/drift_narrator_service.py
index 8bfc6634..5db010d4 100644
--- a/apps/api/src/services/drift_narrator_service.py
+++ b/apps/api/src/services/drift_narrator_service.py
@@ -165,7 +165,25 @@ class DriftNarratorService:
             text, _provider, success = await openclaw.call(prompt)
 
             if success and text and text.strip():
-                return text.strip()
+                # 2026-04-17 ogt + Claude Sonnet 4.6: 修復 JSON 裸奔問題
+                # 根因:openclaw.call() 經 NEMOTRON 路由後強制回傳 JSON(NEMOTRON_SYSTEM_PROMPT 要求)
+                #       但此處需要純文字敘述 → JSON 被直接吐到 Telegram 
 區塊
+                # 修復:嘗試解析 JSON,優先取 description;否則視為純文字使用
+                import json as _json
+                _raw = text.strip()
+                try:
+                    _parsed = _json.loads(_raw)
+                    if isinstance(_parsed, dict):
+                        narrative = (
+                            _parsed.get("description")
+                            or _parsed.get("action_title")
+                            or _parsed.get("reasoning")
+                            or _raw
+                        )
+                        return str(narrative).strip()
+                except (_json.JSONDecodeError, ValueError):
+                    pass
+                return _raw
 
             logger.warning("drift_narrator_openclaw_failed", provider=_provider)