138 lines
5.0 KiB
Python
138 lines
5.0 KiB
Python
"""
|
||
JIANGCHANG_* 数据根与用户目录:解析规则 + 可选本地 CLI 默认值。
|
||
|
||
各技能 scripts/jiangchang_skill_core/ 为发布用副本,与 kit 保持同步。
|
||
|
||
宿主在 skills.entries 与 Gateway 中注入:
|
||
- PATH 前缀:{JIANGCHANG_DATA_ROOT}/python-runtime/.venv/(Scripts|bin)
|
||
- VIRTUAL_ENV、JIANGCHANG_PYTHON_EXE
|
||
Playwright 使用本机 Chrome/Edge(launch 时 channel=chrome|msedge),不依赖宿主下载的 Chromium 包。
|
||
技能勿在仓库内维护独立 .venv;依赖以 jiangchang-platform-kit/python-runtime 锁文件为准。
|
||
"""
|
||
|
||
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",
|
||
"toutiao-publisher",
|
||
"logistics-tracker",
|
||
"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 目录推断并列根;若目录下能识别出兄弟技能
|
||
则用之(开发仓 D:\\OpenClaw 与安装目录 ~/.openclaw/skills 均满足「技能根之上一级 = 并列根」),
|
||
避免全局 JIANGCHANG_SKILLS_ROOT / CLAW_SKILLS_ROOT 指向与当前检出不一致时错调兄弟进程。
|
||
推断失败时再读上述环境变量,最后回落 get_skills_root()。
|
||
"""
|
||
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 os.path.normpath(inferred)
|
||
|
||
for key in ("JIANGCHANG_SKILLS_ROOT", "CLAW_SKILLS_ROOT"):
|
||
v = (os.getenv(key) or "").strip()
|
||
if v:
|
||
return os.path.normpath(v)
|
||
|
||
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()
|