feat: 添加定时任务调度器和相关配置

- 新增定时任务调度器(agentmain.py):支持基于时间戳的任务自动执行
- 添加scheduled_task_sop.md:定时任务执行流程文档
- 优化agent_loop.py:移除错误提示emoji
- 调整sidercall.py:降低context_win至10000
- 更新.gitignore:忽略tasks目录,白名单scheduled_task_sop.md
This commit is contained in:
Liang Jiaqing
2026-02-14 10:10:10 +08:00
parent 4163341bb3
commit 12d79b7847
5 changed files with 38 additions and 3 deletions

4
.gitignore vendored
View File

@@ -33,6 +33,9 @@ auth.json
# 忽略模型响应记录 # 忽略模型响应记录
model_responses.txt model_responses.txt
# 任务调度目录
tasks/
*.zip *.zip
# 存储敏感信息的记忆文件夹(除了公开的 SOP # 存储敏感信息的记忆文件夹(除了公开的 SOP
@@ -42,6 +45,7 @@ memory/*
# Allow tracking of specific SOPs # Allow tracking of specific SOPs
!memory/web_setup_sop.md !memory/web_setup_sop.md
!memory/autonomous_operation_sop.md !memory/autonomous_operation_sop.md
!memory/scheduled_task_sop.md
# ljqCtrl related tools # ljqCtrl related tools
!memory/ljqCtrl.py !memory/ljqCtrl.py

View File

@@ -26,7 +26,7 @@ class BaseHandler:
elif tool_name == 'bad_json': elif tool_name == 'bad_json':
return StepOutcome(None, next_prompt=args.get('msg', 'bad_json'), should_exit=False) return StepOutcome(None, next_prompt=args.get('msg', 'bad_json'), should_exit=False)
else: else:
yield f"未知工具: {tool_name}\n" yield f"未知工具: {tool_name}\n"
return StepOutcome(None, next_prompt=f"未知工具 {tool_name}", should_exit=False) return StepOutcome(None, next_prompt=f"未知工具 {tool_name}", should_exit=False)
def json_default(o): def json_default(o):

View File

@@ -1,4 +1,4 @@
import os, sys, threading, queue, time, json, re import os, sys, threading, queue, time, json, re, random
if sys.stdout is None: sys.stdout = open(os.devnull, "w") if sys.stdout is None: sys.stdout = open(os.devnull, "w")
elif hasattr(sys.stdout, 'reconfigure'): sys.stdout.reconfigure(errors='replace') elif hasattr(sys.stdout, 'reconfigure'): sys.stdout.reconfigure(errors='replace')
if sys.stderr is None: sys.stderr = open(os.devnull, "w") if sys.stderr is None: sys.stderr = open(os.devnull, "w")
@@ -110,3 +110,23 @@ class GeneraticAgent:
if self.handler is not None: self.handler.code_stop_signal.append(1) if self.handler is not None: self.handler.code_stop_signal.append(1)
if __name__ == '__main__':
from datetime import datetime
agent = GeneraticAgent()
threading.Thread(target=agent.run, daemon=True).start()
def drain(dq, tag):
while True:
item = dq.get(); txt = item.get('done') or item.get('next', '')
open('./temp/scheduler_live.log', 'w', encoding='utf-8').write(txt)
if 'done' in item: break
open('./temp/scheduler.log', 'a', encoding='utf-8').write(f'[{datetime.now():%m-%d %H:%M}] {tag}\n{txt}\n\n')
while True:
now = datetime.now()
for f in os.listdir('./tasks/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'./tasks/pending/{f}', encoding='utf-8').read()
dq = agent.put_task(f'按scheduled_task_sop执行任务文件 ./tasks/pending/{f}立刻移到running\n内容:\n{raw}', source='scheduler')
threading.Thread(target=drain, args=(dq, f), daemon=True).start()
break
time.sleep(55 + random.random() * 10)

View File

@@ -0,0 +1,11 @@
# 定时任务 SOP
目录:`../tasks/{pending,running,done}/`
文件名:`YYYY-MM-DD_HHMM_描述.md`内容含prompt和schedule
## 流程
1. [AUTO]唤醒 → `datetime.now()`取当前时间,`ls ../tasks/pending/`,文件名时间≤当前→到期,选择一个
2. **立即rename到running/**(先占再读,防多进程重复领)
3. 读文件执行
4. 完成→移到done/**在文件内追加执行报告**供用户查阅
5. schedule非once→算下次时间新建文件到pending/

View File

@@ -28,7 +28,7 @@ class SiderLLMSession:
return full_text return full_text
class ClaudeSession: class ClaudeSession:
def __init__(self, api_key, api_base, model="claude-opus", context_win=12000): def __init__(self, api_key, api_base, model="claude-opus", context_win=10000):
self.api_key, self.api_base, self.default_model, self.context_win = api_key, api_base.rstrip('/'), model, context_win self.api_key, self.api_base, self.default_model, self.context_win = api_key, api_base.rstrip('/'), model, context_win
self.raw_msgs, self.lock = [], threading.Lock() self.raw_msgs, self.lock = [], threading.Lock()
def _trim_messages(self, messages): def _trim_messages(self, messages):