- 独立 pyproject.toml(pip install -e .) - vendor_hermes.sh 已改为显式路径模式(不再依赖相对目录) - 包含 hermes vendor 快照
117 lines
3.1 KiB
Python
117 lines
3.1 KiB
Python
"""
|
||
Mind CLI — macOS Service 注册。
|
||
|
||
通过 launchd plist 实现 `mind start` 开机自启。
|
||
"""
|
||
|
||
import os
|
||
import platform
|
||
import shutil
|
||
import subprocess
|
||
import sys
|
||
import textwrap
|
||
|
||
_LABEL = "club.brainwork.mindcli"
|
||
_PLIST_DIR = os.path.expanduser("~/Library/LaunchAgents")
|
||
_PLIST_PATH = os.path.join(_PLIST_DIR, f"{_LABEL}.plist")
|
||
_LOG_PATH = os.path.expanduser("~/Library/Logs/mindcli.log")
|
||
|
||
|
||
def _find_mind_executable() -> str:
|
||
"""定位 mind 可执行文件路径。"""
|
||
# 优先使用 which
|
||
result = shutil.which("mind")
|
||
if result:
|
||
return result
|
||
# 回退:当前 Python 的 scripts 目录
|
||
scripts_dir = os.path.join(os.path.dirname(sys.executable), "mind")
|
||
if os.path.isfile(scripts_dir):
|
||
return scripts_dir
|
||
raise FileNotFoundError(
|
||
"找不到 mind 可执行文件。请确认已运行 `pip install -e .` 安装 mindos-cli。"
|
||
)
|
||
|
||
|
||
def install_service() -> None:
|
||
"""
|
||
注册 Mind CLI 为 macOS launchd 服务。
|
||
|
||
生成 plist → launchctl load → 开机自启。
|
||
"""
|
||
if platform.system() != "Darwin":
|
||
print("⚠️ install-service 目前仅支持 macOS。")
|
||
print(" Linux 用户请手动创建 systemd unit。")
|
||
return
|
||
|
||
mind_path = _find_mind_executable()
|
||
os.makedirs(_PLIST_DIR, exist_ok=True)
|
||
|
||
plist_content = textwrap.dedent(f"""\
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
||
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||
<plist version="1.0">
|
||
<dict>
|
||
<key>Label</key>
|
||
<string>{_LABEL}</string>
|
||
|
||
<key>ProgramArguments</key>
|
||
<array>
|
||
<string>{mind_path}</string>
|
||
<string>start</string>
|
||
</array>
|
||
|
||
<key>RunAtLoad</key>
|
||
<true/>
|
||
|
||
<key>KeepAlive</key>
|
||
<true/>
|
||
|
||
<key>StandardOutPath</key>
|
||
<string>{_LOG_PATH}</string>
|
||
|
||
<key>StandardErrorPath</key>
|
||
<string>{_LOG_PATH}</string>
|
||
|
||
<key>ThrottleInterval</key>
|
||
<integer>10</integer>
|
||
</dict>
|
||
</plist>
|
||
""")
|
||
|
||
with open(_PLIST_PATH, "w") as f:
|
||
f.write(plist_content)
|
||
|
||
# launchctl load
|
||
subprocess.run(["launchctl", "load", _PLIST_PATH], check=True)
|
||
|
||
print(f"✅ Mind CLI 已注册为 launchd 服务")
|
||
print(f" Plist: {_PLIST_PATH}")
|
||
print(f" Log: {_LOG_PATH}")
|
||
print(f" Binary: {mind_path}")
|
||
print(f"\n 服务将在登录时自动启动。")
|
||
print(f" 手动启动:launchctl start {_LABEL}")
|
||
print(f" 手动停止:launchctl stop {_LABEL}")
|
||
|
||
|
||
def uninstall_service() -> None:
|
||
"""
|
||
注销 Mind CLI launchd 服务。
|
||
|
||
launchctl unload → 删除 plist。
|
||
"""
|
||
if platform.system() != "Darwin":
|
||
print("⚠️ uninstall-service 目前仅支持 macOS。")
|
||
return
|
||
|
||
if not os.path.isfile(_PLIST_PATH):
|
||
print(f"⚠️ 未找到 plist: {_PLIST_PATH}")
|
||
print(f" Mind CLI 可能未注册为服务。")
|
||
return
|
||
|
||
subprocess.run(["launchctl", "unload", _PLIST_PATH], check=False)
|
||
os.remove(_PLIST_PATH)
|
||
|
||
print(f"✅ Mind CLI 服务已注销")
|
||
print(f" 已删除: {_PLIST_PATH}")
|