From 9219042a8f7b6f73257a6d20f879d0384d69fed1 Mon Sep 17 00:00:00 2001 From: Jiaqing Liang Date: Mon, 2 Mar 2026 23:25:31 +0800 Subject: [PATCH] feat: add --reflect mode with error handling + scheduler/autonomous scripts --- agentmain.py | 30 +++++++++++++++++++++++++++++- reflect/autonomous.py | 6 ++++++ reflect/scheduler.py | 17 +++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 reflect/autonomous.py create mode 100644 reflect/scheduler.py diff --git a/agentmain.py b/agentmain.py index dead59c..71bb589 100644 --- a/agentmain.py +++ b/agentmain.py @@ -125,6 +125,7 @@ if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('--scheduled', action='store_true', help='计划任务轮询模式') parser.add_argument('--task', metavar='IODIR', help='一次性任务模式(文件IO)') + parser.add_argument('--reflect', metavar='SCRIPT', help='反射模式:加载监控脚本,check()触发时发任务') parser.add_argument('--llm_no', type=int, default=0, help='LLM编号') args = parser.parse_args() @@ -149,7 +150,34 @@ if __name__ == '__main__': os.remove(rp); break else: break nround = int(nround) + 1 if nround.isdigit() else 1 - elif args.scheduled: + elif args.reflect: + import importlib.util + spec = importlib.util.spec_from_file_location('reflect_script', args.reflect) + mod = importlib.util.module_from_spec(spec); spec.loader.exec_module(mod) + interval = getattr(mod, 'INTERVAL', 5) + once = getattr(mod, 'ONCE', False) + on_done = getattr(mod, 'on_done', None) + print(f'[Reflect] loaded {args.reflect}, interval={interval}s, once={once}') + while True: + time.sleep(interval) + try: task = mod.check() + except Exception as e: + print(f'[Reflect] check() error: {e}'); continue + if task is None: continue + print(f'[Reflect] triggered: {task[:80]}') + dq = agent.put_task(task, source='reflect') + try: + while 'done' not in (item := dq.get(timeout=120)): pass + result = item['done'] + except Exception as e: + if once: raise + print(f'[Reflect] drain error: {e}'); result = f'[ERROR] {e}' + open('./temp/reflect.log', 'a', encoding='utf-8').write(f'[{datetime.now():%m-%d %H:%M}]\n{result}\n\n') + if on_done: + try: on_done(result) + except Exception as e: print(f'[Reflect] on_done error: {e}') + if once: print('[Reflect] ONCE=True, exiting.'); break + elif args.scheduled: def drain(dq, tag): while 'done' not in (item := dq.get()): pass open('./temp/scheduler.log', 'a', encoding='utf-8').write(f'[{datetime.now():%m-%d %H:%M}] {tag}\n{item["done"]}\n\n') diff --git a/reflect/autonomous.py b/reflect/autonomous.py new file mode 100644 index 0000000..86a7d6e --- /dev/null +++ b/reflect/autonomous.py @@ -0,0 +1,6 @@ +# reflect/autonomous.py +INTERVAL = 1800 +ONCE = False + +def check(): + return "[AUTO]🤖 用户已经离开超过30分钟,作为自主智能体,请阅读自动化sop,执行自动任务。" \ No newline at end of file diff --git a/reflect/scheduler.py b/reflect/scheduler.py new file mode 100644 index 0000000..c3605c5 --- /dev/null +++ b/reflect/scheduler.py @@ -0,0 +1,17 @@ +import os, re +from datetime import datetime + +INTERVAL = 60 # 原版 55+random*10 +ONCE = False + +PENDING = './sche_tasks/pending' + +def check(): + if not os.path.isdir(PENDING): return None + now = datetime.now() + for f in os.listdir(PENDING): + m = re.match(r'(\d{4}-\d{2}-\d{2})_(\d{4})_', f) + if m and now >= datetime.strptime(f'{m[1]} {m[2]}', '%Y-%m-%d %H%M'): + raw = open(f'{PENDING}/{f}', encoding='utf-8').read() + return f'按scheduled_task_sop执行任务文件 ../sche_tasks/pending/{f}(立刻移到running)\n内容:\n{raw}' + return None \ No newline at end of file