test
This commit is contained in:
0
examples/todo_skill/scripts/util/__init__.py
Normal file
0
examples/todo_skill/scripts/util/__init__.py
Normal file
11
examples/todo_skill/scripts/util/argparse_zh.py
Normal file
11
examples/todo_skill/scripts/util/argparse_zh.py
Normal file
@@ -0,0 +1,11 @@
|
||||
"""argparse 中文错误说明(与模板一致)。"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
|
||||
class ZhArgumentParser(argparse.ArgumentParser):
|
||||
def error(self, message: str) -> None:
|
||||
print(f"参数错误:{message}\n请执行:python main.py -h 查看帮助", file=sys.stderr)
|
||||
self.exit(2)
|
||||
24
examples/todo_skill/scripts/util/config_bootstrap.py
Normal file
24
examples/todo_skill/scripts/util/config_bootstrap.py
Normal file
@@ -0,0 +1,24 @@
|
||||
"""配置初始化:从 .env.example 复制到用户 .env,并合并缺失键。
|
||||
|
||||
行为对齐模板:``main.py`` 与 ``cli.app.main()`` 启动时均会调用一次。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
from jiangchang_skill_core import config
|
||||
|
||||
from util.constants import SKILL_SLUG, SKILL_VERSION
|
||||
from util.runtime_paths import get_skill_root
|
||||
|
||||
|
||||
def bootstrap_skill_config() -> str:
|
||||
"""确保用户 .env 存在,并追加 .env.example 中的新配置项。"""
|
||||
example_path = os.path.join(get_skill_root(), ".env.example")
|
||||
if not os.path.isfile(example_path):
|
||||
# demo 没有强制 .env.example,直接返回空路径
|
||||
return ""
|
||||
env_path = config.ensure_env_file(SKILL_SLUG, example_path)
|
||||
comment = f"{SKILL_SLUG} v{SKILL_VERSION}" if SKILL_VERSION else None
|
||||
config.merge_missing_env_keys(example_path, env_path, comment_skill=comment)
|
||||
return env_path
|
||||
11
examples/todo_skill/scripts/util/constants.py
Normal file
11
examples/todo_skill/scripts/util/constants.py
Normal file
@@ -0,0 +1,11 @@
|
||||
"""技能标识与版本(demo:待办事项)。
|
||||
|
||||
真实技能需保证 slug = 目录名 = DB 文件名 = ``metadata.openclaw.slug``。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
# 英文 kebab-case 机器标识;与目录名、actions.json 的 ``skill`` 字段一致
|
||||
SKILL_SLUG = "todo-skill"
|
||||
SKILL_VERSION = "0.1.0"
|
||||
LOG_LOGGER_NAME = "openclaw.skill.todo_skill"
|
||||
PLATFORM_KIT_MIN_VERSION = "1.2.11"
|
||||
29
examples/todo_skill/scripts/util/logging_config.py
Normal file
29
examples/todo_skill/scripts/util/logging_config.py
Normal file
@@ -0,0 +1,29 @@
|
||||
"""日志:直接用 stdlib logging(真实模板用 jiangchang_skill_core.unified_logging)。
|
||||
|
||||
为保持与模板 ``from util.logging_config import get_skill_logger, setup_skill_logging``
|
||||
一致的调用面,本 demo 提供同名薄封装。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from util.constants import LOG_LOGGER_NAME
|
||||
|
||||
_configured = False
|
||||
|
||||
|
||||
def setup_skill_logging(skill_slug: str, logger_name: str) -> None:
|
||||
global _configured
|
||||
if _configured:
|
||||
return
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(name)s: %(message)s"))
|
||||
logger = logging.getLogger(logger_name)
|
||||
logger.setLevel(logging.INFO)
|
||||
if not logger.handlers:
|
||||
logger.addHandler(handler)
|
||||
_configured = True
|
||||
|
||||
|
||||
def get_skill_logger() -> logging.Logger:
|
||||
return logging.getLogger(LOG_LOGGER_NAME)
|
||||
32
examples/todo_skill/scripts/util/runtime_paths.py
Normal file
32
examples/todo_skill/scripts/util/runtime_paths.py
Normal file
@@ -0,0 +1,32 @@
|
||||
"""技能数据目录与 DB 路径解析(简化版)。
|
||||
|
||||
真实模板用 ``jiangchang_skill_core.runtime_env``;本 demo 复用其 mock。
|
||||
数据目录 = ``{data_root}/{user_id}/{slug}/``,DB 即 ``{slug}.db``。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
from jiangchang_skill_core.runtime_env import get_data_root, get_user_id
|
||||
|
||||
from util.constants import SKILL_SLUG
|
||||
|
||||
_SCRIPTS_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
def get_skill_root() -> str:
|
||||
"""技能根目录(含 SKILL.md / scripts/ 的目录)。"""
|
||||
return os.path.dirname(_SCRIPTS_DIR)
|
||||
|
||||
|
||||
def get_skill_data_dir() -> str:
|
||||
"""本技能数据目录:``{data_root}/{user_id}/{slug}/``。"""
|
||||
path = os.path.join(get_data_root(), get_user_id(), SKILL_SLUG)
|
||||
os.makedirs(path, exist_ok=True)
|
||||
return path
|
||||
|
||||
|
||||
def get_db_path(filename: str | None = None) -> str:
|
||||
"""SQLite 文件路径,默认 ``{slug}.db``。"""
|
||||
name = filename or f"{SKILL_SLUG}.db"
|
||||
return os.path.join(get_skill_data_dir(), name)
|
||||
Reference in New Issue
Block a user