From d910338bec4adffee2469dfb93b1691dfec1be90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=94=AF=20A06?= Date: Fri, 10 Jul 2026 03:17:48 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BB=A3=E7=A0=81=E5=AE=A1=E6=9F=A5?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20=E2=80=94=20profile=E8=B7=AF=E5=BE=84/json?= =?UTF-8?q?l=E2=86=92json/sys.modules=E8=A6=86=E5=86=99/timeout/=E5=BE=AA?= =?UTF-8?q?=E7=8E=AFimport/summarize=E9=87=8D=E5=A4=8D=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/daemon.py | 58 ++++++++++++++++++----------------------- scripts/soulful_core.py | 35 +++---------------------- 2 files changed, 28 insertions(+), 65 deletions(-) diff --git a/scripts/daemon.py b/scripts/daemon.py index d8120855..2dfa9c2a 100755 --- a/scripts/daemon.py +++ b/scripts/daemon.py @@ -19,10 +19,10 @@ LLM_CONTEXT_FILE = HERMES + "/llm_context.json" JOURNAL_FILE = D + "/journal.jsonl" SOLUTIONS_FILE = D + "/solutions.json" PID_FILE = D + "/daemon.pid" -LIGHT_INTERVAL = 30 DEEP_INTERVAL = 300 JOURNAL_MAX = 200 PROFILE_UPDATE_INTERVAL = 21600 # 6 hours +LIGHT_INTERVAL = 30 # seconds between ticks # ====== Phase 2: 情感词库(4类)====== EMOTION_TIRED = ["累", "困", "疲惫", "没精神", "打瞌睡"] @@ -70,8 +70,6 @@ FEISHU_WEBHOOK = "https://open.feishu.cn/open-apis/bot/v2/hook/446db983-e392-4d2 API = "http://127.0.0.1:3000/v1" # NewAPI gateway -_stop_event = threading.Event() - # Lazy-loaded soulful modules (avoid import at module load time) _soulful_cache = {} @@ -104,7 +102,7 @@ def call_llm(model, system, user, max_tokens=500): headers={"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}, method="POST"), timeout=15) as resp: body = json.loads(resp.read()) - c = body["choices"][0]["message"]["content"] or "" + c = body.get("choices", [{}])[0].get("message", {}).get("content", "") or "" return c.strip(), body.get("usage", {}).get("total_tokens", 0) except Exception as e: log(f"[call_llm] 请求失败: {e}, 模型: {model}") @@ -390,45 +388,39 @@ def save_context(ctx): def save_llm_context(ctx, state): """每 tick 写 llm_context.json,供 Hermes 插件注入""" - import importlib.util, sys + soulful_d = HERMES + "/soulful" - # 动态加载 soulful_core(避免顶层 import) - spec = importlib.util.spec_from_file_location("soulful_core", HERMES + "/scripts/soulful_core.py") - mod = importlib.util.module_from_spec(spec) - sys.modules["soulful_core"] = mod - if spec.loader is not None: # type: ignore - spec.loader.exec_module(mod) # type: ignore - - soulful_d = mod.HERMES + "/soulful" - - # 读牵挂 + # 读牵挂(直接读 JSON,不 import soulful_core) cares = [] cq_path = soulful_d + "/cares-queue.json" if os.path.exists(cq_path): - with open(cq_path) as f: - data = json.load(f) - for c in data.get("queue", []): - due = c.get("due_date", "") - cares.append({"id": c["id"], "content": c["content"][:60], "due": due}) + try: + with open(cq_path) as f: + data = json.load(f) + for c in data.get("queue", []): + cares.append({"id": c["id"], "content": c["content"][:60], "due": c.get("due_date", "")}) + except Exception: + pass - # 读心迹(最近3条) - heart_path = soulful_d + "/heart-traces.jsonl" + # 读心迹(最近3条,直接读 jsonl) recent_moments = [] + heart_path = soulful_d + "/heart-traces.jsonl" if os.path.exists(heart_path): - lines = open(heart_path).readlines() - for line in lines[-3:]: - if line.strip(): - e = json.loads(line) - recent_moments.append({"content": e["content"][:80], "importance": e.get("importance", 0), "timestamp": e.get("timestamp", "")}) + try: + lines = open(heart_path).readlines() + for line in lines[-3:]: + if line.strip(): + e = json.loads(line) + recent_moments.append({"content": e["content"][:80], "importance": e.get("importance", 0), "timestamp": e.get("timestamp", "")}) + except Exception: + pass - # 读画像(摘要) + # 读画像(user-profile.json 最新行) profile = {} - profile_path = soulful_d + "/user-profile.jsonl" + profile_path = soulful_d + "/user-profile.json" if os.path.exists(profile_path): try: - lines = open(profile_path).readlines() - if lines: - profile = json.loads(lines[-1]) + profile = json.load(open(profile_path)) except Exception: pass @@ -448,7 +440,7 @@ def save_llm_context(ctx, state): "recent_moments": recent_moments, "profile_summary": { "communication_style": profile.get("communication_style", ""), - "work_patterns": profile.get("work_patterns", [])[:3], + "work_patterns": profile.get("work_patterns", {}), }, "os_keywords": os_keywords, "daemon_status": "running" if state.get("processes", {}).get("daemon") else "stopped", diff --git a/scripts/soulful_core.py b/scripts/soulful_core.py index 501e69d0..2b3ebcb7 100644 --- a/scripts/soulful_core.py +++ b/scripts/soulful_core.py @@ -27,14 +27,14 @@ Soulful Core — 织忆情感层核心库 """ import json, os, uuid, requests -from datetime import datetime, timezone +from datetime import datetime, timezone, timedelta from typing import Optional HERMES = os.path.expanduser("~/.hermes") D = HERMES + "/soulful" # 所有数据放 soulful/ 子目录 ZHIYI_URL = "http://127.0.0.1:7821" ZHIYI_KEY = "zhiyi-dev-key-2026" -ZHIYI_TIMEOUT = 10 +ZHIYI_TIMEOUT = 3 def _zhiyi_commit(content: str, category: str = "episodes", importance: int = 3): """Soulful → 织忆:重要心迹写入织忆(importance >= 4)""" @@ -323,7 +323,6 @@ class CaresQueue: for c in cares: if c["id"] == care_id: c["reminder_count"] += 1 - from datetime import timedelta old_date = datetime.strptime(c["follow_up_date"], "%Y-%m-%d") new_date = (old_date + timedelta(days=days)).strftime("%Y-%m-%d") c["follow_up_date"] = new_date @@ -351,7 +350,7 @@ class CaresQueue: """返回今天应该提醒的牵挂(包含昨天到期的)""" today = datetime.now(timezone.utc).strftime("%Y-%m-%d") yesterday = (datetime.now(timezone.utc).replace(hour=0, minute=0, second=0) - - __import__('datetime').timedelta(days=1)).strftime("%Y-%m-%d") + timedelta(days=1)).strftime("%Y-%m-%d") cares = self._load() return [c for c in cares if c["status"] == "pending" @@ -361,34 +360,6 @@ class CaresQueue: # ====== CLI/会话接口 ====== -def summarize(): - """一行获取所有 Soulful 状态""" - ht = HeartTraces() - up = UserProfile() - cq = CaresQueue() - profile = up.get() - recent = ht.recent(n=3) - cares_pending = cq.pending() - cares_due = cq.today_check() or [] - lines = ["【Soulful 状态】"] - style = profile.get("communication_style", "未知") - emotion = profile.get("emotional_state", {}).get("current", "未知") - goals = profile.get("current_goals", []) - lines.append(f"沟通风格: {style} | 情绪: {emotion}") - if goals: - lines.append(f"当前目标: {' / '.join(goals[:3])}") - if recent: - lines.append("最近心迹:") - for m in recent: - lines.append(f" {'★'*m.get('importance', 3)} {m.get('content', '')}") - pending = len(cares_pending) - due = len(cares_due) - lines.append(f"牵挂: {pending}条待跟进,{due}条今日到期") - for c in cares_pending[:3]: - lines.append(f" → {c['content'][:50]}") - return "\n".join(lines) - - # ===== 快捷函数(CLI 入口)===== if __name__ == "__main__":