tamako 在场感知
September 6, 2026 · View on GitHub
一套给 AI 助手(Hermes Agent)用的「主人到场感知 + 自主主动互动」模块:
- 看得见:定时快照主人电脑的"任务层面"状态(前台进程窗口 / 系统空闲 / 进程 CPU 活跃度)
- 记得住:快照落盘为本地时间序列,形成对主人作息与应用的"印象底稿"
- 会好奇:规则引擎把快照和习惯基线比对,产出"值得搭话"的线索(回来了 / 深夜未眠 / 新应用)
- 懂分寸:闸门物理限频(每日上限、冷却、交战沉默、人不在不打扰),agent 无法绕过
- 接得住:每次主动消息都落盘日志,回复上下文丢了也能靠日志把话接上
项目声明:本项目为纯AI生成,可能会出现工作偏差
纯标准库(仅 ctypes 调 Windows API),零第三方依赖,任何 Python 3.8+ 可跑。
目录结构
presence/
├── README.md # 本文档
├── AGENTS.md # 协作守则(给参与开发的 AI/人)
├── config.py # 配置入口:env > config.json > 内置默认
├── config.example.json # 配置示例(复制为 config.json 使用)
├── snapshot.py # 快照采集(前台窗口/空闲/CPU 增量)
├── clue.py # 线索引擎(好奇心规则)
├── gate.py # 互动闸门(限频 + 决策留痕 + 发送登记)
├── topic_seed.py # 话题种子(日记待办/深夜活跃规律 → 素材池)
├── compact.py # 快照压缩(历史按天→月聚合为摘要,保留最近 N 天原始)
├── burn.py # 可焚毁:一键清空运行时数据(--yes 确认)
├── sleep.py # 睡眠标记(on/off/status/active-check,次日 12 点自动失效)
├── logger.py # 统一分级日志(debug/info/warning/error,写 data/presence.log)
├── scripts/ # cron 包装脚本(须复制到 ~/AppData/Local/hermes/scripts/)
│ ├── poll_presence.py # 快照轮询包装(no_agent,静默)
│ ├── gate_pick.py # 闸门候选包装(stdout 注入 [SILENT]/候选)
│ ├── topic_seed_cron.py # 话题种子包装(no_agent,静默)
│ ├── compact_cron.py # 快照压缩包装(no_agent,静默)
│ └── backhome_fast.py # back_home 快速通道(1 分钟内触发,不走 15 分钟轮询)
├── templates/
│ └── proactive_prompt.md # proactive-check cron 的 prompt 模板
└── data/ # 运行时数据(自动生成,不入库)
├── snapshots.jsonl # 快照事件流(机器读)
├── gate_log.jsonl # 闸门决策留痕(每次判断,含沉默原因)
├── sent_log.json # 今日已发送记录
├── active_chat_log.md # 给人看的主动消息日志(YYYY-MM-DD HH:MM 格式)
├── presence.log # 统一分级日志(logger.py 写,JSON 行)
├── current.json # 最新快照
├── pending_clues.json # 待发线索队列(上限 5)
├── clue_state.json # 线索状态(计数/冷却/深夜段)
├── topic_state.json # 话题种子去重表
├── sleep_mode.json # 睡眠标记(sleep.py 写)
└── compacted/ # 压缩摘要副本(<day>.json、<month>.json)
部署步骤
- 放到目标机:整个
presence/目录拷到任意位置(如C:/tools/presence或~/presence,任何你喜欢的路径)。 - 写配置:
cp config.example.json config.json,至少改deliver_target为自己的平台目标 (格式platform:chat_id,QQ 如qqbot:0123456789ABCDEF,微信如weixin:xxxx@im.wechat)。 也可以不改文件,用环境变量PRESENCE_DELIVER_TARGET覆盖。 - 手动验证:
python snapshot.py # 应打印一行 JSON(前台窗口/空闲/模式) python clue.py # NO_CLUE / CLUE: xxx / BUSY_SILENT / IMMERSIVE_SILENT python gate.py status python compact.py --dry-run --keep 2 # 压缩预演(不写盘) python sleep.py status # 睡眠状态查询(SLEEP_OFF 等) - 注册 cron(见下节)。把
scripts/下 5 个包装脚本复制到~/AppData/Local/hermes/scripts/(或~/.hermes/scripts/),并按需改顶部PROJECT_ROOT(或设环境变量PRESENCE_HOME)。 - 注意:packaged scripts 用
sys.executable跑子脚本;如目标机 python 环境特殊, 设PRESENCE_PYTHON指定。
cron 注册(Hermes 侧)
# 1) 快照轮询(每 2 分钟,无 LLM,静默)
hermes cron create "every 2m" "" --name presence-snap \
--script poll_presence.py --no-agent --deliver local
# 2) 主动互动检查(每 15 分钟,LLM 参与生成口吻,正常 [SILENT])
hermes cron create "every 15m" "$(cat templates/proactive_prompt.md)" \
--name proactive-check --script gate_pick.py \
--deliver local --workdir "<项目根绝对路径>"
# 3) 话题种子(每天 07:00 / 21:30,无 LLM,静默)
hermes cron create "0 7 * * *" "" --name presence-seed \
--script topic_seed_cron.py --no-agent --deliver local
hermes cron create "30 21 * * *" "" --name presence-seed-eve \
--script topic_seed_cron.py --no-agent --deliver local
# 4) 快照压缩(每天 00:10,无 LLM,静默;keep=2 天原始,更早聚合为摘要)
hermes cron create "10 0 * * *" "" --name presence-compact \
--script compact_cron.py --no-agent --deliver local
# 5) back_home 快速通道(每 1 分钟,无 LLM,静默)
# 队首是 back_home 且闸门放行→立即发欢迎消息(不走 15 分钟轮询;
# busy/冷却时静默留队,睡眠标记有效时也不发)
hermes cron create "every 1m" "" --name backhome-fast \
--script backhome_fast.py --no-agent --deliver local
注意:proactive-check 是 LLM 型任务,创建后若全局模型配置变更会触发 Hermes 的
drift_skip 保护(任务被跳过、消息不发)。请显式 pin 模型避免:
hermes cron edit <job_id> --provider <provider> --model <model>。
线索类型与情绪
| kind | 触发 | 口吻 |
|---|---|---|
| back_home | 从离开/挂机回到电脑前 | 迎接、想念,轻快 |
| late_night | 深夜(23:00–2:00)还在电脑前 | 心疼、提醒休息 |
| new_app | 前台出现不在 known_apps 的应用 | 好奇、想问 |
| topic_diary | 日记本「待办·监听」条目 | 自然提起,像记得主人的事 |
| topic_habit | 近期深夜活跃规律(7 天内 ≥3 天) | 关心作息 |
快照压缩(compact.py,2026-08-26 新增)
- 策略:保留最近 2 天原始快照(clue/gate 实时判断需要),更早的历史按天聚合为一条摘要 (共性去重:整天同一进程/模式只出现一次;短期保留:窗口切换/模式变化/忙碌段变化点)。
- 跨月时,同月的天摘要再聚合为月摘要。
- 摘要记录含
compacted: true标记,保留ts/mode/idle_s字段(下游兼容),busy置 false(防摘要被误判为实时交战)。 - 摘要副本另存
data/compacted/<day>.json与<month>.json(人读/审计用)。 - 压缩动作本身记入
gate_log.jsonl(kind=compact)。
新增能力(2026-08-25 v0.3 起)
- 决策留痕:闸门每次判断(含"为什么沉默")写入
data/gate_log.jsonl——调试与信任审计用。 - 配置宪法自检:
config.validate()校验关键配置,违规闸门拒跳;deliver_target未配置降级为警告(cron prompt 内置目标时可忽略)。 - 可焚毁:
python burn.py --yes一键清空全部运行时数据(隐私兜底,默认拒绝执行)。 - 协作守则:
AGENTS.md给未来参与者(含 AI)立规矩;config.json已加入 .gitignore(防平台 ID 泄漏入库)。 - 话题种子:
topic_seed.py从日记本待办与深夜活跃规律补充素材池(脱敏、去重、TTL)。 - 快照压缩:
compact.py控制 data 目录长期膨胀(见上节)。
新增能力(2026-08-26 ~ 08-29)
- 开机回家检测(08-26):快照断档 >15 分钟且 18 点后开机 → back_home(reason=
boot_after_18,覆盖"白天关机晚上开机"场景)。 - back_home 停用开关(09-02):
back_home_enabled(默认 true)。设为 false 后 clue.py 不再生成 back_home 线索(回家判定 + 开机回家两处),backhome-fast cron 也随之自然无活可干。本机当前已关闭(config.json)并暂停 backhome-fast cron。 - 睡眠标记
sleep.py(08-26):收到"晚安/要睡了"→sleep.py on [原因]抑制 back_home 等打扰;次日 12 点自动失效;off手动解除,status查询,active-check输出 WOKE/SLEEPING 供下游判断。 - active_chat_log 日期前缀(08-27):日志格式改为
YYYY-MM-DD HH:MM,修复跨会话grep 日期搜不到的问题。 - backhome_fast 快速通道(08-26):back_home 线索 1 分钟内触发,不走 15 分钟轮询;busy/冷却时静默留队。
- 「已醒」自动解除(08-29):睡眠标记有效期内,若快照显示连续活跃 ≥30 分钟 → 自动解除抑制(防"白天关机不在"却标记残留、误吞回家线索);单元测试
tests_sleep_wake.py(8 场景)。 - back_home 重复发送修复(08-29):发送成功判定改为
returncode==0 且无 error;gate.py 增加 back_home 专属冷却(默认 1h);confirm 幂等保护。 - 远程会话识别(08-29):前台命中远程控制名单(UU 远程 GameViewer 系列 / todesk / sunlogin / anydesk / mstsc)→ 快照标记
remote: true+ 强制 mobile(远程串流会重置 idle,防误判回家)。 - 统一分级日志
logger.py(08-29):debug/info/warning/error 四级写入data/presence.log(JSON 行);PRESENCE_LOG_LEVEL或 config.jsonlog_level控制;WARNING 级挂载在冷却拦截/配置警告/线索抑制等"异常但可恢复"场景。 - new_app 线索时效校验(09-06):网络故障期线索滞留、恢复后补发时应用可能已关 → gate pick 前校验 new_app 线索对应进程是否仍在运行,不在则丢弃(gate_log 记 drop_stale)。
红线(默认)
- 每天主动消息 ≤ 30 条;两条间隔 ≥ 30 分钟
- 判定"交战/游戏中"(游戏进程+CPU 高活跃)一律沉默
- 电脑空闲(人不在)不主动
- 只读观察:不操作进程、不读窗口内容/剪贴板/文件
- 主动消息一律问句收尾、短、自然,像真看见了对方
所有阈值都在 config.json 可调。窗口标题默认随快照落盘(用于记忆),
可设 store_title: false 只记录进程名(隐私模式)。调参建议:开跑一周先看 data/active_chat_log.md
和 snapshots.jsonl,再决定哪些应用进 known_apps、频率要不要降。
常见问题
- windows 中文环境乱码:所有读写均为 UTF-8;采集用 Unicode API,无 GBK 问题。
- 拿不到进程名:需要 Windows Vista+(
QueryFullProcessImageNameW)。 - cron 环境 PATH 缺东西:脚本内部只用 ctypes,不依赖外部命令。
- 主动消息后回复丢失:消息本体不在会话上下文是正常的;
data/active_chat_log.md就是为此存在——回复时先看它再开口。 - gate_log 有 ALLOW 但消息没发出:多半是 proactive-check 被 Hermes 的模型配置漂移保护
(drift_skip)拦了。检查 cron job 的 provider/model 是否与当前 config.yaml 一致,
不一致就
hermes cron edit <job_id> --provider <provider> --model <model>显式 pin。