front/xhs-agent-desktop/engine/xhs_bridge/pack_runtime.py
zzh 5a26ae0048 feat: 小红书模块迁移、登录重构与 xhs-agent-desktop 桌面 Agent
- 新增小红书前端模块(启动服务、内容分析、爆款创作、发布记录、技能卡片、拟人设置、AI 助手)

- 新增 xhs-agent-desktop 独立桌面 Agent,对接 OMS 任务调度

- 登录页重构,整合微信登录与 OMS JWT 认证

- 订单、渠道、用户中心等页面与 API 增强

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-30 16:13:13 +08:00

87 lines
2.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""PyInstaller 单文件发布:解压 Chrome 扩展与配置到本地,引擎 exe 从内置 _MEIPASS 运行。"""
from __future__ import annotations
import os
import shutil
import sys
import zipfile
from pathlib import Path
_RUNTIME_APP_NAME = "LikeAI"
_VERSION_FILE = "pack_version.txt"
_EXTENSION_ARCHIVE = "extension.zip"
def _local_runtime_root() -> Path:
base = os.environ.get("LOCALAPPDATA") or os.environ.get("APPDATA") or str(Path.home())
return Path(base) / _RUNTIME_APP_NAME
def _bundle_root() -> Path:
return Path(getattr(sys, "_MEIPASS", Path(__file__).resolve().parent.parent))
def _read_embedded_version() -> str:
path = _bundle_root() / _VERSION_FILE
if path.is_file():
return path.read_text(encoding="utf-8").strip()
return "0"
def bundled_engine_dir() -> Path:
"""单文件内置的 bridge / skills_cli(字节码,无 .py)。"""
return _bundle_root() / "engine"
def is_frozen_app() -> bool:
return bool(getattr(sys, "frozen", False)) and hasattr(sys, "_MEIPASS")
def bootstrap() -> Path:
"""首次运行解压扩展与配置;返回持久化数据目录(配置、.xhs_bridge)。"""
if not is_frozen_app():
return Path(__file__).resolve().parent.parent
root = _local_runtime_root()
root.mkdir(parents=True, exist_ok=True)
version = _read_embedded_version()
stamp = root / ".pack_version"
installed = stamp.read_text(encoding="utf-8").strip() if stamp.is_file() else ""
if installed != version:
_extract_extension(root)
_ensure_config_template(root)
stamp.write_text(version, encoding="utf-8")
return root
def _extract_extension(root: Path) -> None:
archive = _bundle_root() / _EXTENSION_ARCHIVE
if not archive.is_file():
return
ext_dir = root / "extension"
if ext_dir.exists():
shutil.rmtree(ext_dir, ignore_errors=True)
ext_dir.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(archive, "r") as zf:
zf.extractall(ext_dir)
def _ensure_config_template(root: Path) -> None:
target = root / "config.yaml"
if target.is_file():
return
for name in ("config.example.yaml", "config.yaml"):
src = _bundle_root() / name
if src.is_file():
shutil.copy2(src, target)
return
def get_runtime_root() -> Path:
if is_frozen_app():
return bootstrap()
return Path(__file__).resolve().parent.parent