"""CLI:argparse 解析与分发(业务内核在 service,本层只做参数→service 映射)。"""
from __future__ import annotations
import argparse
import sys
from typing import List, Optional
from service.task_service import (
cmd_add,
cmd_config_path,
cmd_delete,
cmd_done,
cmd_health,
cmd_init_db,
cmd_list,
cmd_remind,
cmd_stats,
cmd_version,
cmd_run,
)
from util.config_bootstrap import bootstrap_skill_config
from util.argparse_zh import ZhArgumentParser
from util.constants import LOG_LOGGER_NAME, SKILL_SLUG
from util.logging_config import get_skill_logger, setup_skill_logging
def _cli_str_or_none(raw: Optional[str]) -> Optional[str]:
if raw is None:
return None
v = str(raw).strip()
return v or None
def _parse_ids(raw: str) -> list[int]:
"""解析 ``1`` 或 ``1,2,3`` 为 int 列表。"""
parts = [p.strip() for p in (raw or "").split(",") if p.strip()]
try:
return [int(p) for p in parts]
except ValueError as exc:
raise SystemExit(f"参数错误:ids 必须是数字或逗号分隔的数字列表,收到 {raw!r}\n{exc}")
def _print_full_usage() -> None:
print("通用业务技能模板(main.py)可用命令:")
print(" python main.py init-db # 初始化数据库与元数据")
print(" python main.py todo add
[-p high|normal|low] [-d ")
print(" python main.py todo list [-s pending|done] [-n ]")
print(" python main.py todo done ")
print(" python main.py todo delete ")
print(" python main.py todo stats")
print(" python main.py remind [-s <秒>]")
print(" python main.py health / version / config-path")
def _add_run_subparser(sub) -> None:
sp = sub.add_parser("todo", help="待办事项操作")
todo_sub = sp.add_subparsers(dest="todo_cmd", required=True, parser_class=ZhArgumentParser)
p = todo_sub.add_parser("add", help="新增一条待办")
p.add_argument("-t","--title", help="待办标题(必填)")
p.add_argument("-p", "--priority", default="normal",
choices=["high", "normal", "low"], help="优先级,默认 normal")
p.add_argument("-d", "--due-at", type=int, default=None,
help="截止时间(Unix 秒,可选)")
p.set_defaults(handler=lambda a: cmd_add(
title=a.title, priority=a.priority, due_at=a.due_at))
p = todo_sub.add_parser("list", help="列出待办")
p.add_argument("-s", "--status", default=None,
choices=["pending", "done"], help="按状态过滤")
p.add_argument("-n", "--limit", type=int, default=100, help="返回数量上限")
p.set_defaults(handler=lambda a: cmd_list(status=a.status, limit=a.limit))
p = todo_sub.add_parser("done", help="标记完成(可传逗号分隔的多个 id)")
p.add_argument("ids", help="待办 id 或逗号分隔的 id 列表(如 1 或 1,2,3)")
p.set_defaults(handler=lambda a: cmd_done(todo_ids=_parse_ids(a.ids)))
p = todo_sub.add_parser("delete", help="删除(可传逗号分隔的多个 id)")
p.add_argument("ids", help="待办 id 或逗号分隔的 id 列表")
p.set_defaults(handler=lambda a: cmd_delete(todo_ids=_parse_ids(a.ids)))
p = todo_sub.add_parser("stats", help="简单统计")
p.set_defaults(handler=lambda _a: cmd_stats())
def _add_remind_subparser(sub) -> None:
sp = sub.add_parser("remind", help="演示 async 提醒任务(job_context/emit/finish)")
sp.add_argument("-s", "--seconds", type=int, default=3,
help="模拟运行秒数,默认 3")
sp.set_defaults(handler=lambda a: cmd_remind(seconds=a.seconds))
def build_parser() -> ZhArgumentParser:
p = ZhArgumentParser(
prog="main.py",
description="待办事项",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
sub = p.add_subparsers(dest="cmd", required=True, parser_class=ZhArgumentParser)
sp = sub.add_parser("init-db", help="幂等初始化 SQLite 与数据管理元数据")
sp.set_defaults(handler=lambda _a: cmd_init_db())
_add_run_subparser(sub)
_add_remind_subparser(sub)
sp = sub.add_parser("health", help="健康检查")
sp.set_defaults(handler=lambda _a: cmd_health())
sp = sub.add_parser("version", help="版本信息(JSON)")
sp.set_defaults(handler=lambda _a: cmd_version())
sp = sub.add_parser("config-path", help="输出 .env 与模板路径")
sp.set_defaults(handler=lambda _a: cmd_config_path())
sp = sub.add_parser("run", help="运行占位符")
sp.set_defaults(handler=lambda _a: cmd_run())
return p
def main(argv: Optional[List[str]] = None) -> int:
argv = argv if argv is not None else sys.argv[1:]
bootstrap_skill_config()
setup_skill_logging(SKILL_SLUG, LOG_LOGGER_NAME)
get_skill_logger().info("cli_start argv=%s", sys.argv)
if not argv:
_print_full_usage()
return 1
if len(argv) == 2 and argv[0] not in {
"run", "health", "config-path", "version", "init-db",
"-h", "--help",
}:
return cmd_run(target=argv[0], input_id=argv[1])
parser = build_parser()
args = parser.parse_args(argv)
return int(args.handler(args))