diff --git a/scripts/jiangchang_skill_core/runtime_env.py b/scripts/jiangchang_skill_core/runtime_env.py index dcde0ab..7ea0169 100644 --- a/scripts/jiangchang_skill_core/runtime_env.py +++ b/scripts/jiangchang_skill_core/runtime_env.py @@ -1,53 +1,127 @@ -""" -JIANGCHANG_* 数据根与用户目录:解析规则 + 可选本地 CLI 默认值。 - -各技能 scripts/jiangchang_skill_core/ 为发布用副本,与 kit 保持同步。 -""" - -from __future__ import annotations - -import os -import sys - -# 发版/嵌入宿主前改为 False,或仅通过环境变量 JIANGCHANG_CLI_LOCAL_DEV=1 开启 -CLI_LOCAL_DEV_ENABLED = True - -# 本地开发且未设置 JIANGCHANG_USER_ID 时注入(与宿主约定一致即可修改) -DEFAULT_LOCAL_USER_ID = "10032" - -# Windows 下未设置 JIANGCHANG_DATA_ROOT 时的默认盘路径 -WIN_DEFAULT_DATA_ROOT = r"D:\jiangchang-data" - - -def platform_default_data_root() -> str: - if sys.platform == "win32": - return WIN_DEFAULT_DATA_ROOT - return os.path.join(os.path.expanduser("~"), ".jiangchang-data") - - -def get_data_root() -> str: - env = (os.getenv("JIANGCHANG_DATA_ROOT") or "").strip() - if env: - return env - return platform_default_data_root() - - -def get_user_id() -> str: - return (os.getenv("JIANGCHANG_USER_ID") or "").strip() or "_anon" - - -def apply_cli_local_defaults() -> None: - """ - 在 CLI 最早阶段调用(main.py 在 import 业务包之前)。 - 宿主已设置 JIANGCHANG_* 时不会覆盖。 - """ - enabled = CLI_LOCAL_DEV_ENABLED - if not enabled: - v = (os.getenv("JIANGCHANG_CLI_LOCAL_DEV") or "").strip().lower() - enabled = v in ("1", "true", "yes", "on") - if not enabled: - return - if not (os.getenv("JIANGCHANG_DATA_ROOT") or "").strip(): - os.environ["JIANGCHANG_DATA_ROOT"] = platform_default_data_root() - if not (os.getenv("JIANGCHANG_USER_ID") or "").strip(): - os.environ["JIANGCHANG_USER_ID"] = DEFAULT_LOCAL_USER_ID.strip() +""" +JIANGCHANG_* 数据根与用户目录:解析规则 + 可选本地 CLI 默认值。 + +各技能 scripts/jiangchang_skill_core/ 为发布用副本,与 kit 保持同步。 +""" + +from __future__ import annotations + +import os +import sys + +# 发版/嵌入宿主前改为 False,或仅通过环境变量 JIANGCHANG_CLI_LOCAL_DEV=1 开启 +CLI_LOCAL_DEV_ENABLED = True + +# 本地开发且未设置 JIANGCHANG_USER_ID 时注入(与宿主约定一致即可修改) +DEFAULT_LOCAL_USER_ID = "10032" + +# Windows 下未设置 JIANGCHANG_DATA_ROOT 时的默认盘路径 +WIN_DEFAULT_DATA_ROOT = r"D:\jiangchang-data" + +# 匠厂桌面宿主应用根(未设置 JIANGCHANG_APP_ROOT 时 Windows 兜底;技能一般在 {APP}/skills/ 下并列) +WIN_DEFAULT_JIANGCHANG_APP_ROOT = r"D:\AI\jiangchang" + + +def platform_default_data_root() -> str: + if sys.platform == "win32": + return WIN_DEFAULT_DATA_ROOT + return os.path.join(os.path.expanduser("~"), ".jiangchang-data") + + +def get_data_root() -> str: + env = (os.getenv("JIANGCHANG_DATA_ROOT") or "").strip() + if env: + return env + return platform_default_data_root() + + +def get_user_id() -> str: + return (os.getenv("JIANGCHANG_USER_ID") or "").strip() or "_anon" + + +def _looks_like_skills_root(path: str) -> bool: + if not path or not os.path.isdir(path): + return False + for marker in ( + "llm-manager", + "content-manager", + "account-manager", + "sohu-publisher", + "api-key-vault", + ): + if os.path.isdir(os.path.join(path, marker)): + return True + return False + + +def get_skills_root() -> str: + """ + 并列技能安装目录(其下为「技能 slug」子目录)。 + + 优先级: + 1) JIANGCHANG_SKILLS_ROOT + 2) CLAW_SKILLS_ROOT + 3) JIANGCHANG_APP_ROOT:若 {APP}/skills 存在且像技能根则用之;否则若 APP 下已有技能子目录则 APP 即根 + 4) Windows:默认 D:\\AI\\jiangchang 同上规则 + 5) 其他平台:~/.openclaw/skills + """ + for key in ("JIANGCHANG_SKILLS_ROOT", "CLAW_SKILLS_ROOT"): + v = (os.getenv(key) or "").strip() + if v: + return os.path.normpath(v) + + app = (os.getenv("JIANGCHANG_APP_ROOT") or "").strip() + if sys.platform == "win32" and not app: + app = WIN_DEFAULT_JIANGCHANG_APP_ROOT + if app: + nested = os.path.join(app, "skills") + if _looks_like_skills_root(nested): + return os.path.normpath(nested) + if _looks_like_skills_root(app): + return os.path.normpath(app) + + if sys.platform == "win32": + nested = os.path.join(WIN_DEFAULT_JIANGCHANG_APP_ROOT, "skills") + if _looks_like_skills_root(nested): + return os.path.normpath(nested) + if _looks_like_skills_root(WIN_DEFAULT_JIANGCHANG_APP_ROOT): + return os.path.normpath(WIN_DEFAULT_JIANGCHANG_APP_ROOT) + + return os.path.normpath(os.path.join(os.path.expanduser("~"), ".openclaw", "skills")) + + +def get_sibling_skills_root(skill_scripts_dir: str | None = None) -> str: + """ + 编排子进程调用兄弟技能时用:优先环境变量;否则从本技能 scripts 目录推断并列根 + (OpenClaw 开发仓与网关 skills//scripts 均满足「技能根之上一级 = 并列根」)。 + """ + for key in ("JIANGCHANG_SKILLS_ROOT", "CLAW_SKILLS_ROOT"): + v = (os.getenv(key) or "").strip() + if v: + return os.path.normpath(v) + + if skill_scripts_dir: + scripts = os.path.abspath(skill_scripts_dir) + skill_root = os.path.dirname(scripts) + inferred = os.path.dirname(skill_root) + if _looks_like_skills_root(inferred): + return inferred + + return get_skills_root() + + +def apply_cli_local_defaults() -> None: + """ + 在 CLI 最早阶段调用(main.py 在 import 业务包之前)。 + 宿主已设置 JIANGCHANG_* 时不会覆盖。 + """ + enabled = CLI_LOCAL_DEV_ENABLED + if not enabled: + v = (os.getenv("JIANGCHANG_CLI_LOCAL_DEV") or "").strip().lower() + enabled = v in ("1", "true", "yes", "on") + if not enabled: + return + if not (os.getenv("JIANGCHANG_DATA_ROOT") or "").strip(): + os.environ["JIANGCHANG_DATA_ROOT"] = platform_default_data_root() + if not (os.getenv("JIANGCHANG_USER_ID") or "").strip(): + os.environ["JIANGCHANG_USER_ID"] = DEFAULT_LOCAL_USER_ID.strip()