Files
GenericAgent/reflect/checklist_master.py
T
dd3xp b1352f2de1 chore: sync framework to upstream lsdefine/GenericAgent @ b365945
上次同步点是 1eb8c4c (我们 fork 上为 8f89766),lsdefine 自那以来 102 个

commit,包括飞书 IM 插件、TUI v2 修、conductor OOP 重构、L4 scheduler

mkdir 修复、checklist 系统、computer_use SOP 等。

处理分桶:

  - 45 个 lsdefine-only 文件:整文件覆盖(safe,无我方改动)

  - 17 个 ours-only 文件:完全保留(桌面前端 + bridge + plan_state)

  - 4 个双方都动:逐个 3-way 合

      * .gitignore: 取并集(lsdefine 新增 + 我们 /BUG_*.md)

      * reflect/scheduler.py: 已字节对齐 lsdefine,无操作

      * frontends/conductor.py: lsdefine OOP 重构作 base,我们 6 处

          改动(CORS / add_chat files+images / cost_tracker / token-stats

          / WS running / WS receive files+images)原样塞进新结构

      * frontends/conductor.html: lsdefine 重组作 base,我们 40 行

          输入字数限制 + toast 原样塞进 keydown 监听之后

未触动 desktop_bridge.py(memory 规则约定 exclude bridge)。

已 grep 全文件无 <<<<<< / ======= / >>>>>> 冲突标记残留。

我们改动一行未漏,全部按原代码原文落实,没有自创新代码。
2026-06-06 23:05:59 +08:00

67 lines
2.4 KiB
Python
Raw 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.
import json, time, random
from pathlib import Path
from urllib import request
INTERVAL = 60
ONCE = False
_folder = None
_last_post_id = -1
def init(a):
global _folder
_folder = Path(a.get('mr_folder', ''))
def _load():
p = _folder / "state.json"
if not p.exists(): return None
return json.loads(p.read_text("utf-8"))
def _poll_bbs(data):
global _last_post_id
bbs = data.get("bbs")
if not bbs: return []
url, key = bbs.get("url", ""), bbs.get("key", "")
if not url: return []
try:
req = request.Request(f"{url}/posts?limit=20&key={key}")
posts = json.loads(request.urlopen(req, timeout=10).read())
if not posts: return []
new = [p for p in posts if p['id'] > _last_post_id]
_last_post_id = max(p['id'] for p in posts)
return new
except Exception:
return []
def check():
check.times = getattr(check, "times", 0) + 1
if check.times > 1000: return '/exit'
if not _folder: return '/exit'
data = _load()
if not data or data.get("closed"): return '/exit'
bbs = data.get("bbs")
if not bbs: return _prompt(data, [])
# mapreduce: 轮询BBS
new_posts = _poll_bbs(data)
tasks = data.get("tasks", [])
has_open = any(t["result"] is None for t in tasks)
if new_posts and has_open: return _prompt(data, new_posts)
if not has_open and (not tasks or random.random() < 0.2): return _prompt(data, new_posts)
return None
def _prompt(data, new_posts):
bbs = data.get("bbs")
goal = data.get("goal", "")
mode = "mapreduce" if bbs else "checklist"
if new_posts:
trigger = "有新回帖,去BBS查看并验收"
elif any(t["result"] is None for t in data.get("tasks", [])):
trigger = "有未完成任务,继续执行" if not bbs else "有未完成任务,派发"
else: trigger = "无未完成任务,该plan下一步了"
lines = [f"你是 Checklist Master({mode}模式)。阅读 checklist_sop.md 21行之后按 Master 行事。"]
if bbs: lines.append(f"BBS API文档(requests): GET {bbs['url']}/readme?key={bbs['key']}")
lines.append(f"目标: {goal}")
lines.append(f"唤醒原因: {trigger}")
lines.append(f'用 checklist_helper 的 CL("{_folder}") 管理状态(look/add/mark/close)。按决策树行动。')
if bbs: lines.append("【禁止】你只负责派发+轮询+验收,绝不自己执行任务。")
return "\n".join(lines)