release: runtime_env marker, SKILL v1.0.51
All checks were successful
技能自动化发布 / release (push) Successful in 25s

This commit is contained in:
2026-04-08 12:05:14 +08:00
parent beb95c1415
commit 4605d3d0e4
2 changed files with 13 additions and 131 deletions

View File

@@ -1,7 +1,7 @@
--- ---
name: 账号管理 name: 账号管理
description: 多平台多账号管理。管理各平台账号与Chrome Profile的对应关系供publisher类Skill调用获取账号信息。 description: 多平台多账号管理。管理各平台账号与Chrome Profile的对应关系供publisher类Skill调用获取账号信息。
version: 1.0.50 version: 1.0.51
author: 深圳匠厂科技有限公司 author: 深圳匠厂科技有限公司
metadata: metadata:
openclaw: openclaw:
@@ -14,6 +14,10 @@ allowed-tools:
# 账号管理 # 账号管理
## JIANGCHANG 共享 Python匠厂桌面
依赖由宿主安装到 `{JIANGCHANG_DATA_ROOT}/python-runtime/.venv`(技能市场安装时自动 `uv sync`)。勿在技能目录内创建 `.venv`。Playwright 浏览器目录:`{JIANGCHANG_DATA_ROOT}/playwright-browsers``PLAYWRIGHT_BROWSERS_PATH`)。
## 使用时机 ## 使用时机
当用户发送以下内容的时候触发本Skill 当用户发送以下内容的时候触发本Skill

View File

@@ -1,258 +1,136 @@
""" """
JIANGCHANG_* 数据根与用户目录:解析规则 + 可选本地 CLI 默认值。 JIANGCHANG_* 数据根与用户目录:解析规则 + 可选本地 CLI 默认值。
各技能 scripts/jiangchang_skill_core/ 为发布用副本,与 kit 保持同步。 各技能 scripts/jiangchang_skill_core/ 为发布用副本,与 kit 保持同步。
宿主在 skills.entries 与 Gateway 中注入:
- PATH 前缀:{JIANGCHANG_DATA_ROOT}/python-runtime/.venv/(Scripts|bin)
- PLAYWRIGHT_BROWSERS_PATH、VIRTUAL_ENV、JIANGCHANG_PYTHON_EXE
技能勿在仓库内维护独立 .venv依赖以 jiangchang-platform-kit/python-runtime 锁文件为准。
""" """
from __future__ import annotations from __future__ import annotations
import os import os
import sys import sys
# 发版/嵌入宿主前改为 False或仅通过环境变量 JIANGCHANG_CLI_LOCAL_DEV=1 开启 # 发版/嵌入宿主前改为 False或仅通过环境变量 JIANGCHANG_CLI_LOCAL_DEV=1 开启
CLI_LOCAL_DEV_ENABLED = True CLI_LOCAL_DEV_ENABLED = True
# 本地开发且未设置 JIANGCHANG_USER_ID 时注入(与宿主约定一致即可修改) # 本地开发且未设置 JIANGCHANG_USER_ID 时注入(与宿主约定一致即可修改)
DEFAULT_LOCAL_USER_ID = "10032" DEFAULT_LOCAL_USER_ID = "10032"
# Windows 下未设置 JIANGCHANG_DATA_ROOT 时的默认盘路径 # Windows 下未设置 JIANGCHANG_DATA_ROOT 时的默认盘路径
WIN_DEFAULT_DATA_ROOT = r"D:\jiangchang-data" WIN_DEFAULT_DATA_ROOT = r"D:\jiangchang-data"
# 匠厂桌面宿主应用根(未设置 JIANGCHANG_APP_ROOT 时 Windows 兜底;技能一般在 {APP}/skills/ 下并列) # 匠厂桌面宿主应用根(未设置 JIANGCHANG_APP_ROOT 时 Windows 兜底;技能一般在 {APP}/skills/ 下并列)
WIN_DEFAULT_JIANGCHANG_APP_ROOT = r"D:\AI\jiangchang" WIN_DEFAULT_JIANGCHANG_APP_ROOT = r"D:\AI\jiangchang"
def platform_default_data_root() -> str: def platform_default_data_root() -> str:
if sys.platform == "win32": if sys.platform == "win32":
return WIN_DEFAULT_DATA_ROOT return WIN_DEFAULT_DATA_ROOT
return os.path.join(os.path.expanduser("~"), ".jiangchang-data") return os.path.join(os.path.expanduser("~"), ".jiangchang-data")
def get_data_root() -> str: def get_data_root() -> str:
env = (os.getenv("JIANGCHANG_DATA_ROOT") or "").strip() env = (os.getenv("JIANGCHANG_DATA_ROOT") or "").strip()
if env: if env:
return env return env
return platform_default_data_root() return platform_default_data_root()
def get_user_id() -> str: def get_user_id() -> str:
return (os.getenv("JIANGCHANG_USER_ID") or "").strip() or "_anon" return (os.getenv("JIANGCHANG_USER_ID") or "").strip() or "_anon"
def _looks_like_skills_root(path: str) -> bool: def _looks_like_skills_root(path: str) -> bool:
if not path or not os.path.isdir(path): if not path or not os.path.isdir(path):
return False return False
for marker in ( for marker in (
"llm-manager", "llm-manager",
"content-manager", "content-manager",
"account-manager", "account-manager",
"sohu-publisher", "sohu-publisher",
"toutiao-publisher",
"logistics-tracker",
"api-key-vault", "api-key-vault",
): ):
if os.path.isdir(os.path.join(path, marker)): if os.path.isdir(os.path.join(path, marker)):
return True return True
return False return False
def get_skills_root() -> str: def get_skills_root() -> str:
""" """
并列技能安装目录(其下为「技能 slug」子目录 并列技能安装目录(其下为「技能 slug」子目录
优先级: 优先级:
1) JIANGCHANG_SKILLS_ROOT 1) JIANGCHANG_SKILLS_ROOT
2) CLAW_SKILLS_ROOT 2) CLAW_SKILLS_ROOT
3) JIANGCHANG_APP_ROOT{APP}/skills 存在且像技能根则用之;否则若 APP 下已有技能子目录则 APP 即根 3) JIANGCHANG_APP_ROOT{APP}/skills 存在且像技能根则用之;否则若 APP 下已有技能子目录则 APP 即根
4) Windows默认 D:\\AI\\jiangchang 同上规则 4) Windows默认 D:\\AI\\jiangchang 同上规则
5) 其他平台:~/.openclaw/skills 5) 其他平台:~/.openclaw/skills
""" """
for key in ("JIANGCHANG_SKILLS_ROOT", "CLAW_SKILLS_ROOT"): for key in ("JIANGCHANG_SKILLS_ROOT", "CLAW_SKILLS_ROOT"):
v = (os.getenv(key) or "").strip() v = (os.getenv(key) or "").strip()
if v: if v:
return os.path.normpath(v) return os.path.normpath(v)
app = (os.getenv("JIANGCHANG_APP_ROOT") or "").strip() app = (os.getenv("JIANGCHANG_APP_ROOT") or "").strip()
if sys.platform == "win32" and not app: if sys.platform == "win32" and not app:
app = WIN_DEFAULT_JIANGCHANG_APP_ROOT app = WIN_DEFAULT_JIANGCHANG_APP_ROOT
if app: if app:
nested = os.path.join(app, "skills") nested = os.path.join(app, "skills")
if _looks_like_skills_root(nested): if _looks_like_skills_root(nested):
return os.path.normpath(nested) return os.path.normpath(nested)
if _looks_like_skills_root(app): if _looks_like_skills_root(app):
return os.path.normpath(app) return os.path.normpath(app)
if sys.platform == "win32": if sys.platform == "win32":
nested = os.path.join(WIN_DEFAULT_JIANGCHANG_APP_ROOT, "skills") nested = os.path.join(WIN_DEFAULT_JIANGCHANG_APP_ROOT, "skills")
if _looks_like_skills_root(nested): if _looks_like_skills_root(nested):
return os.path.normpath(nested) return os.path.normpath(nested)
if _looks_like_skills_root(WIN_DEFAULT_JIANGCHANG_APP_ROOT): if _looks_like_skills_root(WIN_DEFAULT_JIANGCHANG_APP_ROOT):
return os.path.normpath(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")) return os.path.normpath(os.path.join(os.path.expanduser("~"), ".openclaw", "skills"))
def get_sibling_skills_root(skill_scripts_dir: str | None = None) -> str: def get_sibling_skills_root(skill_scripts_dir: str | None = None) -> str:
""" """
编排子进程调用兄弟技能时用:先根据本技能 scripts 目录推断并列根;若目录下能识别出兄弟技能 编排子进程调用兄弟技能时用:先根据本技能 scripts 目录推断并列根;若目录下能识别出兄弟技能
则用之(开发仓 D:\\OpenClaw 与安装目录 ~/.openclaw/skills 均满足「技能根之上一级 = 并列根」),
则用之(开发仓与安装目录均满足「技能根之上一级 = 并列根」), 避免全局 JIANGCHANG_SKILLS_ROOT / CLAW_SKILLS_ROOT 指向与当前检出不一致时错调兄弟进程。
避免全局 JIANGCHANG_SKILLS_ROOT / CLAW_SKILLS_ROOT 与当前检出不一致时错调兄弟进程。
推断失败时再读上述环境变量,最后回落 get_skills_root()。 推断失败时再读上述环境变量,最后回落 get_skills_root()。
""" """
if skill_scripts_dir: if skill_scripts_dir:
scripts = os.path.abspath(skill_scripts_dir) scripts = os.path.abspath(skill_scripts_dir)
skill_root = os.path.dirname(scripts) skill_root = os.path.dirname(scripts)
inferred = os.path.dirname(skill_root) inferred = os.path.dirname(skill_root)
if _looks_like_skills_root(inferred): if _looks_like_skills_root(inferred):
return os.path.normpath(inferred) return os.path.normpath(inferred)
for key in ("JIANGCHANG_SKILLS_ROOT", "CLAW_SKILLS_ROOT"): for key in ("JIANGCHANG_SKILLS_ROOT", "CLAW_SKILLS_ROOT"):
v = (os.getenv(key) or "").strip() v = (os.getenv(key) or "").strip()
if v: if v:
return os.path.normpath(v) return os.path.normpath(v)
return get_skills_root() return get_skills_root()
def apply_cli_local_defaults() -> None: def apply_cli_local_defaults() -> None:
""" """
在 CLI 最早阶段调用main.py 在 import 业务包之前)。 在 CLI 最早阶段调用main.py 在 import 业务包之前)。
宿主已设置 JIANGCHANG_* 时不会覆盖。 宿主已设置 JIANGCHANG_* 时不会覆盖。
""" """
enabled = CLI_LOCAL_DEV_ENABLED enabled = CLI_LOCAL_DEV_ENABLED
if not enabled: if not enabled:
v = (os.getenv("JIANGCHANG_CLI_LOCAL_DEV") or "").strip().lower() v = (os.getenv("JIANGCHANG_CLI_LOCAL_DEV") or "").strip().lower()
enabled = v in ("1", "true", "yes", "on") enabled = v in ("1", "true", "yes", "on")
if not enabled: if not enabled:
return return
if not (os.getenv("JIANGCHANG_DATA_ROOT") or "").strip(): if not (os.getenv("JIANGCHANG_DATA_ROOT") or "").strip():
os.environ["JIANGCHANG_DATA_ROOT"] = platform_default_data_root() os.environ["JIANGCHANG_DATA_ROOT"] = platform_default_data_root()
if not (os.getenv("JIANGCHANG_USER_ID") or "").strip(): if not (os.getenv("JIANGCHANG_USER_ID") or "").strip():
os.environ["JIANGCHANG_USER_ID"] = DEFAULT_LOCAL_USER_ID.strip() os.environ["JIANGCHANG_USER_ID"] = DEFAULT_LOCAL_USER_ID.strip()