This commit is contained in:
2026-09-09 10:29:02 +08:00
parent 2aa49b5263
commit ccb12dad7c
102 changed files with 7879 additions and 559 deletions

0
scripts/util/__init__.py Normal file
View File

View File

@@ -1,5 +1,4 @@
"""argparse 中文错误说明。"""
"""argparse 中文错误说明(与模板一致)。"""
from __future__ import annotations
import argparse

View File

@@ -1,5 +1,7 @@
"""技能配置初始化:.env.example 落盘与用户 .env 缺失项合并。"""
"""配置初始化:从 .env.example 复制到用户 .env,并合并缺失键。
行为对齐模板:``main.py`` 与 ``cli.app.main()`` 启动时均会调用一次。
"""
from __future__ import annotations
import os
@@ -11,8 +13,11 @@ from util.runtime_paths import get_skill_root
def bootstrap_skill_config() -> str:
"""确保用户数据目录 .env 存在,并追加 .env.example 中的新配置项。"""
"""确保用户 .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)

View File

@@ -1,6 +1,11 @@
"""技能标识、版本与平台公共库约束(复制后请修改 slug/version/logger)。"""
"""技能标识与版本(待办事项)。
真实技能需保证 slug = 目录名 = DB 文件名 = ``metadata.openclaw.slug``。
"""
from __future__ import annotations
# 英文 kebab-case 机器标识;与目录名、actions.json 的 ``skill`` 字段一致
SKILL_SLUG = "add-todo-all"
SKILL_VERSION = "1.0.98"
LOG_LOGGER_NAME = "openclaw.skill.add_todo_all"
SKILL_VERSION = "0.1.0"
LOG_LOGGER_NAME = "openclaw.skill.add-todo-all"
PLATFORM_KIT_MIN_VERSION = "1.2.11"

View File

@@ -1,21 +1,33 @@
"""Re-export unified logging (implementation: jiangchang_skill_core.unified_logging)."""
"""日志:直接用 stdlib logging(真实模板用 jiangchang_skill_core.unified_logging)。
from jiangchang_skill_core.unified_logging import (
attach_unified_file_handler,
ensure_trace_for_process,
get_skill_log_file_path,
get_skill_logger,
get_unified_logs_dir,
setup_skill_logging,
subprocess_env_with_trace,
)
为保持与模板 ``from util.logging_config import get_skill_logger, setup_skill_logging``
一致的调用面,本 demo 提供同名薄封装。
"""
from __future__ import annotations
__all__ = [
"attach_unified_file_handler",
"ensure_trace_for_process",
"get_skill_log_file_path",
"get_skill_logger",
"get_unified_logs_dir",
"setup_skill_logging",
"subprocess_env_with_trace",
]
import logging
import jiangchang_skill_core.unified_logging as unified_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
unified_logging.setup_skill_logging(skill_slug, logger_name)
def get_skill_logger() -> logging.Logger:
#return logging.getLogger(LOG_LOGGER_NAME)
return unified_logging.get_skill_logger()

View File

@@ -1,10 +1,13 @@
"""数据根、技能目录、兄弟技能根路径与用户数据子目录解析。"""
"""技能数据目录与 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_sibling_skills_root, get_user_id
from jiangchang_skill_core.runtime_env import get_data_root, get_user_id
from util.constants import SKILL_SLUG
@@ -32,28 +35,22 @@ CONFIG_KEY_TEMP_DIR = "SKILL_TEMP_DIR"
def get_skill_root() -> str:
"""技能根目录(含 SKILL.md / scripts/ 的目录)。"""
return os.path.dirname(_SCRIPTS_DIR)
def get_openclaw_root() -> str:
return get_sibling_skills_root(_SCRIPTS_DIR)
def get_skills_root() -> str:
return get_sibling_skills_root(_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)
def _normalize_subdir(value: str) -> str:
cleaned = value.strip().strip("/\\")
if not cleaned or cleaned.startswith(".."):
@@ -153,3 +150,4 @@ def list_resolved_data_paths() -> dict[str, str]:
"temp_dir": get_temp_dir(create=False),
"videos_dir": get_videos_dir(create=False),
}

View File

@@ -66,8 +66,8 @@ LEGACY_EXEMPT_SLUGS: frozenset[str] = frozenset(
{
"account-manager",
"skill-template",
"add-todo-all",
"add_todo_all",
"your-skill-slug",
"your_skill_slug",
}
)