xiaowei-system/scripts/os_sense.py

167 lines
5.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
os_sense.py — 织忆 Soulful OS 无感感知
============================
轻量感知牧尘当前在做什么项目,不侵入隐私。
用法:
python3 os_sense.py # 可读摘要
python3 os_sense.py --json # JSON 输出
"""
import json, os, sys, re
from datetime import datetime
from pathlib import Path
from collections import Counter
HOME = Path.home()
HERMES = HOME / ".hermes"
MC = HOME / "mc"
STOPWORDS = {"织忆", "小唯", "hermes", "python", "文件", "修改", "更新",
"", "", "", "", "", "", "", "", "",
"这个", "那个", "什么", "怎么", "为什么", "", "",
"", "", "如果", "因为", "所以", "虽然", "不过",
"还是", "可以", "", "", "", "没有", "", ""}
CONFIG_FILES = [
HERMES / "SOUL.md",
HERMES / "AGENTS.md",
HERMES / "config.yaml",
]
def get_recent_files(n=10):
"""最近修改的 md 文件"""
md_files = list((MC).rglob("*.md")) if MC.exists() else []
md_files = [(f, os.path.getmtime(f)) for f in md_files]
md_files.sort(key=lambda x: x[1], reverse=True)
return [{"path": str(f.relative_to(HOME)), "mtime": datetime.fromtimestamp(m).isoformat()}
for f, m in md_files[:n]]
def get_project_keywords(n=5):
"""从最近 Wiki 概念文件中提取项目关键词"""
concepts = MC / "小唯" / "07-Wiki" / "concepts"
if not concepts.exists():
return []
files = list(concepts.glob("*.md"))
files.sort(key=lambda f: os.path.getmtime(f), reverse=True)
keywords = []
for f in files[:n]:
name = f.stem
# 去掉日期前缀
name = re.sub(r'^\d+-', '', name)
# 提取有意义的词
for part in re.split(r'[-_]', name):
if len(part) > 1 and part not in STOPWORDS:
keywords.append(part)
return list(set(keywords))[:5]
def get_journal_keywords(n=50):
"""从 journal 统计高频词"""
journal_path = HERMES / "daemon" / "journal.jsonl"
if not journal_path.exists():
return [], []
words = []
try:
with open(journal_path) as f:
lines = f.readlines()
recent = lines[-n:] if len(lines) > n else lines
for line in recent:
try:
entry = json.loads(line)
text = entry.get("summary", "") + " " + entry.get("action_taken", "")
# 简单分词(英文)+ 中文词提取(\w 不匹配中文)
tokens = re.findall(r'[\w]{2,}', text.lower())
chinese_words = re.findall(r'[\u4e00-\u9fff]{2,}', text)
tokens = [t for t in tokens if t not in STOPWORDS and len(t) > 1]
chinese_words = [w for w in chinese_words if w not in STOPWORDS]
words.extend(tokens + chinese_words)
except:
pass
except:
pass
if not words:
return [], []
counter = Counter(words)
top = counter.most_common(10)
return [w for w, _ in top], top
def check_config_change():
"""检查是否有重大配置变更"""
results = []
for f in CONFIG_FILES:
if f.exists():
mtime = os.path.getmtime(f)
results.append({"file": f.name, "mtime": datetime.fromtimestamp(mtime).isoformat()})
return results
def generate_summary(projects, keywords, recent_files):
"""生成自然语言摘要"""
parts = []
if keywords:
parts.append("".join(keywords[:3]))
if recent_files:
latest = recent_files[0]
# 从路径提取项目名
path_parts = Path(latest["path"]).parts
if len(path_parts) >= 2:
parts.append(f"最近在看 {path_parts[-2]}")
if not parts:
return "牧尘最近没有明显的工作模式变化"
return f"牧尘这周/这段时间在关注:{', '.join(parts)}"
def sense():
recent_files = get_recent_files(10)
project_keywords = get_project_keywords(5)
journal_keywords, journal_freq = get_journal_keywords(50)
config_files = check_config_change()
summary = generate_summary(project_keywords, journal_keywords, recent_files)
# 判断是否有新方向config 改变)
config_change = len(config_files) > 0
return {
"projects": project_keywords,
"recent_files": recent_files[:5],
"keywords": journal_keywords[:8],
"config_change": config_change,
"config_files": config_files,
"summary": summary,
"sensed_at": datetime.now().isoformat(),
}
def print_human(data):
print(f"🖥️ OS 感知报告 — {data['sensed_at'][:10]}")
print()
if data["recent_files"]:
print("📁 最近在看的文件:")
for f in data["recent_files"][:5]:
print(f" {f['path']}")
print()
if data["keywords"]:
print(f"🔍 工作关键词:{' '.join(data['keywords'][:8])}")
print()
if data["projects"]:
print(f"📂 项目方向:{' '.join(data['projects'])}")
print()
if data["config_change"]:
print("⚙️ 配置有变更:")
for cf in data["config_files"]:
print(f" {cf['file']}{cf['mtime'][:10]}")
print()
print(f"💭 {data['summary']}")
if __name__ == "__main__":
data = sense()
if "--json" in sys.argv:
print(json.dumps(data, ensure_ascii=False, indent=2))
else:
print_human(data)