Files
sproutclaw-cron/cronctl.py
shumengya c10cacd5c6 feat: 多语言任务、WebUI 增强与 Agent MCP 集成
重构 lib 为扁平模块并支持 Windows schtasks;新增 JS/Bash/PowerShell 模板、WebUI 调度编辑,以及 Cursor Skill 与 MCP 工具供 Agent 管理定时任务。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-24 21:45:25 +08:00

111 lines
3.3 KiB
Python
Executable File
Raw Permalink 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.
#!/usr/bin/env python3
"""shumengya cron 任务开关与运行管理。"""
from __future__ import annotations
import argparse
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent / "lib"))
from manager import (
cron_root,
get_context,
iter_task_ids,
migrate_legacy_disabled_layout,
run_task,
set_task_state,
sync_cron_d,
)
from runner import task_enabled_text, task_is_enabled
CRON_ROOT = cron_root()
def _resolve_task_ids(values: list[str]) -> list[str]:
if not values:
return iter_task_ids(CRON_ROOT)
if len(values) == 1 and values[0] == "all":
return iter_task_ids(CRON_ROOT)
return values
def _print_status(task_id: str) -> None:
ctx = get_context(task_id, CRON_ROOT)
print(f"{ctx.task_id}: {task_enabled_text(ctx)}")
def _set_state(task_id: str, enabled: bool) -> None:
_info, message = set_task_state(task_id, enabled, CRON_ROOT)
print(f"{task_id}: {'开启' if enabled else '关闭'}")
if message:
print(f"{message}")
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(
prog="cronctl.py",
description="管理 /shumengya/project/agent/sproutclaw-cron 下每个定时任务的开关状态,或手动执行任务。",
)
parser.add_argument(
"action",
nargs="?",
default="status",
choices=["status", "enable", "disable", "toggle", "on", "off", "run", "sync-cron"],
help="status / enable / disable / toggle / run / sync-cron",
)
parser.add_argument("tasks", nargs="*", help="任务名status 时默认列出全部;也可传 all")
args = parser.parse_args(argv)
migrate_legacy_disabled_layout(CRON_ROOT)
action = args.action
if action == "on":
action = "enable"
elif action == "off":
action = "disable"
task_ids = _resolve_task_ids(list(args.tasks))
if not task_ids:
print("未找到可管理的任务。", file=sys.stderr)
return 1
if action in {"enable", "disable", "toggle", "run", "sync-cron"} and not args.tasks:
print("请至少指定一个任务名,或传 all。", file=sys.stderr)
return 1
rc = 0
for task_id in task_ids:
try:
if action == "run":
task_rc = run_task(task_id, CRON_ROOT)
marker = ">" if sys.platform == "win32" else ""
print(f"{marker} {task_id} (exit={task_rc})")
if task_rc != 0:
rc = task_rc
continue
if action == "status":
_print_status(task_id)
elif action == "sync-cron":
ctx = get_context(task_id, CRON_ROOT)
message = sync_cron_d(ctx, task_is_enabled(ctx))
if message:
print(f"{message}")
elif action == "enable":
_set_state(task_id, True)
elif action == "disable":
_set_state(task_id, False)
else:
_set_state(task_id, not task_is_enabled(get_context(task_id, CRON_ROOT)))
except FileNotFoundError as e:
print(str(e), file=sys.stderr)
rc = 1
return rc
if __name__ == "__main__":
raise SystemExit(main())