#!/usr/bin/env python3 """whereami.py — xác định PHÒNG BAN (topic) HIỆN TẠI trong nhóm, từ METADATA (chat_id + thread_id), KHÔNG đoán từ nội dung chat. Dùng để: trả lời "đang ở phòng nào" + ĐỊNH TUYẾN ngữ cảnh theo phòng. Cơ chế: Telegram gắn `message_thread_id` cho mỗi topic. Hermes lưu phiên dạng `agent:main:telegram:group::` trong sessions.json → tách ra (chat_id, thread_id). Map thread_id → tên phòng từ registry `departments_setup` (tên→thread, do setup_departments lưu). Anchor vào sessions.json vì env đôi khi là phiên DM (không phản ánh nhóm). python3 lib/whereami.py -> JSON {in_group, chat_id, thread_id, topic} """ import os import sys import json sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import identity def _latest_group(cid_filter=None): """(chat_id, thread_id) của phiên NHÓM cập nhật MỚI NHẤT trong sessions.json. Lọc theo cid_filter (chat nhóm hiện tại) nếu có. Đây là nguồn ĐÁNG TIN cho thread_id: mỗi tin trong 1 topic cập nhật session `...:group::` của topic đó → phiên mới nhất = topic HIỆN TẠI. (Đối chiếu env: Hermes có thể bơm HERMES_SESSION_THREAD_ID/KEY KẸT ở topic trước vào subprocess — quan sát thực tế env kẹt 197 dù user ở topic khác → mọi phòng bị nhận nhầm Marketing. Nên KHÔNG tin env thread.)""" try: sp = os.path.join(os.path.expanduser("~"), ".hermes", "sessions", "sessions.json") data = json.load(open(sp, encoding="utf-8")) cands = [] for k, v in data.items(): if ":group:" not in str(k): continue rest = k.split(":group:", 1)[1].split(":") cid = rest[0] tid = rest[1] if len(rest) > 1 else "1" if cid_filter and cid != str(cid_filter): continue cands.append((v.get("updated_at", ""), cid, tid)) if cands: cands.sort() return cands[-1][1], cands[-1][2] except Exception: pass return "", "" def _group_session(): """(chat_id, thread_id) của phiên NHÓM hiện tại. CHAT_ID: env id âm là đáng tin (dùng để lọc đúng nhóm). THREAD_ID: KHÔNG tin env — Hermes có thể bơm thread/KEY cũ kẹt ở topic trước; nguồn đúng = phiên nhóm cập nhật mới nhất trong sessions.json. Chỉ rơi về env khi sessions.json chưa có phiên nhóm nào (cold-start).""" env_cid = (os.environ.get("HERMES_SESSION_CHAT_ID") or "").strip() env_tid = (os.environ.get("HERMES_SESSION_THREAD_ID") or "").strip() cid_filter = env_cid if env_cid.startswith("-") else None sess_cid, sess_tid = _latest_group(cid_filter) if sess_cid: return sess_cid, sess_tid if env_cid.startswith("-"): return env_cid, (env_tid or "1") return "", "" def main(): cid, tid = _group_session() if not cid: print(json.dumps({"ok": True, "in_group": False, "topic": None, "note": "Đang ở DM (chat riêng), không ở trong nhóm/phòng ban nào."}, ensure_ascii=False)) return 0 user_id = identity.resolve_user() topic = None idx = identity.load_index() users = idx.get("users", {}) rec = users.get(user_id, {}) if user_id else {} # Trong NHÓM, Hermes thường chỉ lộ chat_id nhóm (id âm) → resolve_user() = tg_, # KHÔNG phải user đã chạy setup_departments (registry nằm dưới CEO). Nên KHÔNG phụ thuộc mình # record của resolve_user: fallback sang BẤT KỲ record nào có departments_chat_id == chat_id nhóm. # Nhờ vậy mọi thành viên trong nhóm đều map đúng phòng ban, không chỉ người sở hữu registry. if not rec.get("departments_setup"): for cand in users.values(): if str(cand.get("departments_chat_id") or "") == str(cid) and cand.get("departments_setup"): rec = cand break try: mp = json.loads(rec.get("departments_setup", "{}") or "{}") # tên -> thread_id rev = {str(v): k for k, v in mp.items()} topic = rev.get(str(tid)) except Exception: pass if not topic and str(tid) in ("1", ""): topic = "Chung (General)" print(json.dumps({"ok": True, "in_group": True, "chat_id": cid, "thread_id": tid, "topic": topic}, ensure_ascii=False)) return 0 if __name__ == "__main__": sys.exit(main())