- 原生 fnOS 应用(CGI 入口 + Python 守护进程),依赖 python312 运行时 - 三平台签到:TRAE 每日 200 积分、WorkBuddy 7 天循环、Qoder 每日 100 Credits - WorkBuddy 网页授权(OAuth 设备流)、TRAE icubeAuth 解密 Token、Qoder Cosy 设备头 - 多时段调度(默认 00:05/09:00/12:30/19:00)、启动补跑、幂等签到+回查确认 - 多平台 Webhook 通知(企业微信/钉钉/飞书/Bark/Server酱/PushPlus 自动识别) - Qoder 双站点 Token 隔离自动探测与修复 - 前端:仪表盘/账号管理/签到记录/设置四个页签,30s 轮询+变化检测+隐藏暂停 - 测试:34 后端 + 25 E2E + 9 前端回归 + 真实时钟调度测试
79 lines
2.7 KiB
Python
79 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Real-clock scheduling test: set a slot 1 minute ahead, start the daemon,
|
|
and verify it fires the scheduled run on its own."""
|
|
import json
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tarfile
|
|
import time
|
|
|
|
ROOT = "/vol1/@appshare/fn-deepseek-harness/fnos-agent-checkin"
|
|
SIM = "/tmp/fnos-sim"
|
|
APPDEST = SIM + "/var/apps/AgentCheckin"
|
|
PKGVAR = SIM + "/appdata/AgentCheckin"
|
|
TARGET = APPDEST + "/target"
|
|
BACKEND = TARGET + "/backend"
|
|
|
|
shutil.rmtree(SIM, ignore_errors=True)
|
|
os.makedirs(APPDEST)
|
|
os.makedirs(PKGVAR)
|
|
os.makedirs(SIM + "/pkg")
|
|
subprocess.run(f"tar xzf {ROOT}/AgentCheckin/AgentCheckin.fpk -C {SIM}/pkg", shell=True, check=True)
|
|
with tarfile.open(SIM + "/pkg/app.tgz") as t:
|
|
t.extractall(TARGET)
|
|
for item in ("cmd", "config", "manifest", "wizard"):
|
|
src, dst = f"{SIM}/pkg/{item}", f"{APPDEST}/{item}"
|
|
shutil.copytree(src, dst) if os.path.isdir(src) else shutil.copy(src, dst)
|
|
subprocess.run(f"chmod +x {TARGET}/ui/index.cgi {APPDEST}/cmd/*", shell=True)
|
|
|
|
env = dict(os.environ, TRIM_APPDEST=APPDEST, TRIM_PKGVAR=PKGVAR)
|
|
subprocess.run(f"TRIM_PKGVAR={PKGVAR} bash {APPDEST}/cmd/install_callback",
|
|
shell=True, env=env, check=True)
|
|
|
|
add_account = (
|
|
"import sys; sys.path.insert(0, %r)\n"
|
|
"import engine\n"
|
|
"engine.add_trae('sched-test', 'eyJhbGciOiJSUzI1NiJ9.eyJ1c2VyUmVnaW9uIjp7InJlZ2lvbiI6IkNOIn19.sig')\n"
|
|
) % BACKEND
|
|
subprocess.run([sys.executable, "-c", add_account], env=env, check=True,
|
|
capture_output=True)
|
|
|
|
slot = time.strftime("%H:%M", time.localtime(time.time() + 60))
|
|
set_slot = (
|
|
"import sys; sys.path.insert(0, %r)\n"
|
|
"import common\n"
|
|
"s = common.load_settings(); s['schedule_times'] = [%r]\n"
|
|
"common.save_settings(s)\n"
|
|
"print('slot:', %r)\n"
|
|
) % (BACKEND, slot, slot)
|
|
r = subprocess.run([sys.executable, "-c", set_slot], env=env, check=True,
|
|
capture_output=True, text=True)
|
|
print(r.stdout.strip(), "| now:", time.strftime("%H:%M:%S"))
|
|
|
|
r = subprocess.run(f"bash {APPDEST}/cmd/main start", shell=True, env=env,
|
|
capture_output=True, text=True)
|
|
print("start:", r.stdout.strip() or r.stderr.strip())
|
|
|
|
deadline = time.time() + 170
|
|
fired = None
|
|
while time.time() < deadline:
|
|
try:
|
|
st = json.load(open(PKGVAR + "/state.json"))
|
|
except (OSError, ValueError):
|
|
time.sleep(3)
|
|
continue
|
|
reason = st.get("last_run_reason", "")
|
|
if reason.startswith("schedule:"):
|
|
fired = reason
|
|
break
|
|
time.sleep(3)
|
|
|
|
subprocess.run(f"bash {APPDEST}/cmd/main stop", shell=True, env=env,
|
|
capture_output=True)
|
|
print("SCHEDULED RUN:", fired)
|
|
ok = fired == "schedule:" + slot
|
|
print("RESULT:", "PASS" if ok else "FAIL")
|
|
sys.exit(0 if ok else 1)
|