初始化测试通过
This commit is contained in:
@@ -41,19 +41,19 @@ def _parse_ids(raw: str) -> list[int]:
|
||||
|
||||
|
||||
def _print_full_usage() -> None:
|
||||
print("待办事项 add-todo-all(main.py)可用命令:")
|
||||
print("通用业务技能模板(main.py)可用命令:")
|
||||
print(" python main.py init-db # 初始化数据库与元数据")
|
||||
print(" python main.py run add <title> [-p high|normal|low] [-d <unix秒>")
|
||||
print(" python main.py run list [-s pending|done] [-n <limit>]")
|
||||
print(" python main.py run done <id>")
|
||||
print(" python main.py run delete <id>")
|
||||
print(" python main.py run stats")
|
||||
print(" python main.py todo add <title> [-p high|normal|low] [-d <unix秒>")
|
||||
print(" python main.py todo list [-s pending|done] [-n <limit>]")
|
||||
print(" python main.py todo done <id>")
|
||||
print(" python main.py todo delete <id>")
|
||||
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("run", help="待办事项操作")
|
||||
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="新增一条待办")
|
||||
@@ -114,6 +114,9 @@ def build_parser() -> ZhArgumentParser:
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@ from db.display_metadata import (
|
||||
upsert_table_metadata,
|
||||
)
|
||||
from util.runtime_paths import get_db_path
|
||||
from db.timestamp_columns import init_updated_at_trigger
|
||||
|
||||
ALL_BUSINESS_TABLES:tuple[str, ...] = ("todos")
|
||||
|
||||
# ---- 业务表 DDL(待办事项)----
|
||||
# 字段顺序 = 数据管理列展示顺序;状态/优先级用 options_json 给宿主做下拉筛选
|
||||
@@ -26,8 +29,8 @@ CREATE TABLE IF NOT EXISTS todos (
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
priority TEXT NOT NULL DEFAULT 'normal',
|
||||
due_at INTEGER,
|
||||
created_at INTEGER NOT NULL,
|
||||
updated_at INTEGER NOT NULL
|
||||
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
||||
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
||||
)
|
||||
"""
|
||||
|
||||
@@ -40,6 +43,12 @@ def get_conn() -> sqlite3.Connection:
|
||||
return sqlite3.connect(get_db_path())
|
||||
|
||||
|
||||
def _init_business_timestamp_triggers(cursor) -> None:
|
||||
""" for table_name in ALL_BUSINESS_TABLES:
|
||||
init_updated_at_trigger(cursor, table_name) """
|
||||
init_updated_at_trigger(cursor, "todos")
|
||||
|
||||
|
||||
def _seed_todos_display_metadata(cursor) -> None:
|
||||
"""写 ``todos`` 表与字段的中文展示元数据。"""
|
||||
upsert_table_metadata(
|
||||
@@ -70,11 +79,11 @@ def _seed_todos_display_metadata(cursor) -> None:
|
||||
"visible": 1, "searchable": 1, "editable": 0, "display_type": "enum",
|
||||
"options_json": '[{"value":"high","label":"高"},{"value":"normal","label":"中"},{"value":"low","label":"低"}]'},
|
||||
{"column_name": "due_at", "display_name": "截止时间", "description": "Unix 秒;可空",
|
||||
"visible": 1, "searchable": 1, "editable": 0, "display_type": "datetime_unix_seconds"},
|
||||
"visible": 1, "searchable": 1, "editable": 0, "display_type": "datetime_unix_seconds","default":"(unixepoch())"},
|
||||
{"column_name": "created_at", "display_name": "创建时间", "description": "Unix 秒",
|
||||
"visible": 1, "searchable": 0, "editable": 0, "display_type": "datetime_unix_seconds"},
|
||||
"visible": 1, "searchable": 0, "editable": 0, "display_type": "datetime_unix_seconds","default":"(unixepoch())"},
|
||||
{"column_name": "updated_at", "display_name": "更新时间", "description": "Unix 秒",
|
||||
"visible": 0, "searchable": 0, "editable": 0, "display_type": "datetime_unix_seconds"},
|
||||
"visible": 0, "searchable": 0, "editable": 0, "display_type": "datetime_unix_seconds","default":"(unixepoch())"},
|
||||
],
|
||||
)
|
||||
|
||||
@@ -89,8 +98,11 @@ def init_db() -> None:
|
||||
# 2. 业务表
|
||||
cur.execute(_TODOS_DDL)
|
||||
cur.execute(_TODOS_INDEX)
|
||||
_init_business_timestamp_triggers(cur)
|
||||
# 3. 业务表展示元数据
|
||||
_seed_todos_display_metadata(cur)
|
||||
|
||||
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
@@ -13,6 +13,7 @@ import json
|
||||
import os
|
||||
import time
|
||||
from typing import Any, Optional
|
||||
import uuid
|
||||
|
||||
from jiangchang_skill_core import collect_runtime_diagnostics, config, format_runtime_health_lines
|
||||
from jiangchang_skill_core.activity import JobStopped, emit, finish, job_context
|
||||
@@ -68,7 +69,7 @@ async def _run_template_demo(target: Optional[str], input_id: Optional[str]) ->
|
||||
def cmd_run(target: Optional[str] = None, input_id: Optional[str] = None) -> int:
|
||||
"""通用任务执行入口模板。复制后请实现真实业务逻辑。"""
|
||||
log = _get_task_logger()
|
||||
task_type = "cmd_run"
|
||||
task_type = "demo"
|
||||
|
||||
with job_context(skill=SKILL_SLUG):
|
||||
log.info(
|
||||
@@ -223,7 +224,7 @@ def cmd_add(*, title: str, priority: str = "normal", due_at: Optional[int] = Non
|
||||
try:
|
||||
todo = todo_service.add_todo(title=title, priority=priority, due_at=due_at)
|
||||
except ValueError as exc:
|
||||
print(f"ERROR:TODO_INVALID: {exc}")
|
||||
_get_task_logger().error(f"ERROR:TODO_INVALID: {exc}")
|
||||
return 1
|
||||
_get_task_logger().info(json.dumps(todo.to_dict(), ensure_ascii=False))
|
||||
return 0
|
||||
@@ -266,7 +267,7 @@ async def _run_remind_async(*, seconds: int) -> dict[str, Any]:
|
||||
"""
|
||||
steps = max(1, int(seconds))
|
||||
for i in range(1, steps + 1):
|
||||
await asyncio.sleep(1)
|
||||
await interruptible_sleep(1)
|
||||
emit(f"提醒任务进度 {i}/{steps}", skill=SKILL_SLUG, stage="remind", progress=i, total=steps)
|
||||
# 真实业务在这里会查 todos 表挑出 due/pending 项发出提醒;demo 不做真实推送
|
||||
summary = todo_service.stats()
|
||||
|
||||
@@ -10,8 +10,12 @@ from __future__ import annotations
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
import logging
|
||||
|
||||
from db.connection import get_conn
|
||||
from util.logging_config import get_skill_logger, setup_skill_logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 业务常量(不暴露给宿主,技能自定)
|
||||
STATUS_PENDING = "pending"
|
||||
@@ -59,8 +63,10 @@ def add_todo(
|
||||
"""新增一条待办。领域校验:标题非空、优先级合法。"""
|
||||
title = (title or "").strip()
|
||||
if not title:
|
||||
logger.warning("标题不能为空")
|
||||
raise ValueError("标题不能为空")
|
||||
if priority not in VALID_PRIORITY:
|
||||
logger.warning(f"优先级不合法,可选:{sorted(VALID_PRIORITY)}")
|
||||
raise ValueError(f"优先级不合法,可选:{sorted(VALID_PRIORITY)}")
|
||||
now = _now()
|
||||
conn = get_conn()
|
||||
@@ -84,6 +90,7 @@ def list_todos(*, status: Optional[str] = None, limit: int = 100) -> list[Todo]:
|
||||
params: list = []
|
||||
if status:
|
||||
if status not in VALID_STATUS:
|
||||
logger.warning(f"状态不合法,可选:{sorted(VALID_STATUS)}")
|
||||
raise ValueError(f"状态不合法,可选:{sorted(VALID_STATUS)}")
|
||||
sql += " WHERE status = ?"
|
||||
params.append(status)
|
||||
@@ -118,8 +125,10 @@ def mark_done(todo_id: int) -> Todo:
|
||||
"""标记一条待办为完成。"""
|
||||
todo = get_todo(todo_id)
|
||||
if not todo:
|
||||
logger.warning(f"待办 {todo_id} 不存在")
|
||||
raise ValueError(f"待办 {todo_id} 不存在")
|
||||
if todo.status == STATUS_DONE:
|
||||
logger.warning(f"待办 {todo_id} 已是完成状态")
|
||||
raise ValueError(f"待办 {todo_id} 已是完成状态")
|
||||
now = _now()
|
||||
conn = get_conn()
|
||||
|
||||
@@ -9,3 +9,7 @@ SKILL_SLUG = "add-todo-all"
|
||||
SKILL_VERSION = "0.1.0"
|
||||
LOG_LOGGER_NAME = "openclaw.skill.add-todo-all"
|
||||
PLATFORM_KIT_MIN_VERSION = "1.2.11"
|
||||
|
||||
#定义业务表
|
||||
TODOS_TABLE = "todos"
|
||||
BUSINESS_TABLES:tuple[str, ...] = (TODOS_TABLE,)
|
||||
|
||||
Reference in New Issue
Block a user