Files
cbb a3b84d5ce2 feat: AgentCheckin v1.2.2 — fnOS 应用:TRAE/WorkBuddy/Qoder 三平台每日积分自动签到
- 原生 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 前端回归 + 真实时钟调度测试
2026-10-13 19:09:48 +08:00

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)