From a030cc0a0e1cc712a29fa293174cba38260438c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=94=AF=20A06?= Date: Thu, 30 Jul 2026 11:54:15 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20opencode=20code=20review=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - cbm-to-zhiyi.py: 防止 KeyError(.get 防御) - cbm-query-wrapper.py: 异常细化 + 环境变量读取 API key + nodes/edges 类型安全 - update_profile.py: 变更检测避免冗余写入 + agent_id 统一为 a06 --- scripts/cbm-query-wrapper.py | 34 +++++++++++++++++++++------------- scripts/cbm-to-zhiyi.py | 5 ++++- scripts/update_profile.py | 34 ++++++++++++++++++++++++---------- 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/scripts/cbm-query-wrapper.py b/scripts/cbm-query-wrapper.py index 5328c232..297bf468 100755 --- a/scripts/cbm-query-wrapper.py +++ b/scripts/cbm-query-wrapper.py @@ -6,11 +6,11 @@ cbm-query-wrapper.py — P3: CBM 查询钩子 python3 cbm-query-wrapper.py search_graph --project X --name-pattern Y python3 cbm-query-wrapper.py get_architecture --project X """ -import json, os, subprocess, sys, urllib.request +import json, os, subprocess, sys, urllib.request, urllib.error CBM = os.path.expanduser("~/.local/bin/codebase-memory-mcp") ZHIYI_URL = "http://localhost:7821/api/v1/commit" -ZHIYI_KEY = "zhiyi-dev-key-2026" +ZHIYI_KEY = os.environ.get("ZHIYI_API_KEY", "zhiyi-dev-key-2026") def zhiyi_write(content, category="distilled"): """写入织忆""" @@ -23,14 +23,23 @@ def zhiyi_write(content, category="distilled"): headers={"X-API-Key": ZHIYI_KEY, "Content-Type": "application/json"}) try: urllib.request.urlopen(req, timeout=5) - except Exception: - pass # 写入失败不影响主查询 + return True + except urllib.error.URLError as e: + print(f"[cbm-wrapper] ⚠ 织忆写入失败: {e}", file=sys.stderr) + return False def run_cbm(args): """执行 CBM CLI 并返回 JSON 结果""" cmd = [CBM, "cli"] + args - result = subprocess.run(cmd, capture_output=True, text=True, timeout=60) - return result.stdout, result.returncode + try: + result = subprocess.run(cmd, capture_output=True, text=True, timeout=60) + return result.stdout, result.returncode + except FileNotFoundError: + print(f"[cbm-wrapper] ❌ CBM binary not found: {CBM}", file=sys.stderr) + return "", 1 + except subprocess.TimeoutExpired: + print(f"[cbm-wrapper] ⚠ CBM timed out (60s)", file=sys.stderr) + return "", 1 def main(): if len(sys.argv) < 2: @@ -51,23 +60,22 @@ def main(): try: data = json.loads(stdout) project = data.get("project", data.get("name", "unknown")) - nodes = data.get("nodes", data.get("total_nodes", 0)) - edges = data.get("edges", data.get("total_edges", 0)) + nodes = data.get("nodes") or data.get("total_nodes") or 0 + edges = data.get("edges") or data.get("total_edges") or 0 - if tool in ("index_repository",) and nodes: + if tool in ("index_repository",) and int(nodes) > 0: content = f"CBM索引完成: {project} ({nodes}节点/{edges}边)" zhiyi_write(content) elif tool in ("get_architecture", "list_projects"): - # 只保存摘要 content = f"CBM架构查询: {project}" zhiyi_write(content) elif tool in ("search_graph", "trace_path"): - results = data.get("results", data.get("nodes", [])) + results = data.get("results") or data.get("nodes") or [] if results: names = [r.get("name","?") for r in results[:5]] - content = f"CBM查询 '{' '.join(sys.argv)}': 找到 {len(results)} 个结果 ({', '.join(names)})" + content = f"CBM查询 '{tool}': 找到 {len(results)} 个结果 ({', '.join(names)})" zhiyi_write(content) - except (json.JSONDecodeError, KeyError): + except (json.JSONDecodeError, KeyError, TypeError, ValueError): pass # 非 JSON 输出或不匹配模式就不写入 if __name__ == "__main__": diff --git a/scripts/cbm-to-zhiyi.py b/scripts/cbm-to-zhiyi.py index 68fd358e..dd87eb15 100644 --- a/scripts/cbm-to-zhiyi.py +++ b/scripts/cbm-to-zhiyi.py @@ -29,7 +29,10 @@ def main(): lines = ["CBM代码图谱状态:"] for p in projects: - lines.append(f" • {p['name']}: {p['nodes']}节点/{p['edges']}边") + name = p.get('name', '?') + nodes = p.get('nodes', 0) + edges = p.get('edges', 0) + lines.append(f" • {name}: {nodes}节点/{edges}边") content = "\n".join(lines) # 写入织忆 diff --git a/scripts/update_profile.py b/scripts/update_profile.py index f339d1c7..4e04e87f 100644 --- a/scripts/update_profile.py +++ b/scripts/update_profile.py @@ -312,15 +312,29 @@ def main(): # ── P1: Soulful → 织忆 ────────────────────────────────── profile = up.get() - style = profile.get("communication_style", "unknown") - goals = profile.get("current_goals", []) - emotion = profile.get("emotional_state", {}).get("current", "unknown") - content = f"用户画像更新: 风格={style} 情绪={emotion} 目标={', '.join(goals[:3])}" - try: - zhiyi_write(content, "distilled") - print(f" ✓ 画像 → 织忆") - except Exception as e: - print(f" ⚠ 织忆写入失败: {e}") + style = profile.get("communication_style", style) # 用 fresh 检测值优先 + goals = profile.get("current_goals", goals) + emotion = profile.get("emotional_state", {}).get("current", emotion) + + # 变更检测:只有画像发生变化才写入织忆 + last_hash_file = os.path.join(HERMES, "soulful", ".last_zhiyi_hash") + current_hash = f"{style}|{emotion}|{','.join(goals[:3])}" + last_hash = "" + if os.path.exists(last_hash_file): + with open(last_hash_file) as f: + last_hash = f.read().strip() + + if current_hash != last_hash: + content = f"用户画像更新: 风格={style} 情绪={emotion} 目标={', '.join(goals[:3])}" + try: + zhiyi_write(content, "distilled") + with open(last_hash_file, 'w') as f: + f.write(current_hash) + print(f" ✓ 画像 → 织忆") + except Exception as e: + print(f" ⚠ 织忆写入失败: {e}") + else: + print(f" - 画像无变化,跳过织忆写入") # ── P1 End ────────────────────────────────────────────── @@ -330,7 +344,7 @@ def zhiyi_write(content: str, category: str = "distilled"): payload = json.dumps({ "content": content, "category": category, - "agent_id": "hermes-a06" + "agent_id": "a06" }).encode() req = urllib.request.Request( "http://localhost:7821/api/v1/commit",