Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- 专家市场默认打开「精选」,用书签标出接入市场前随安装包提供的 22 个专家模板

### 修复
- macOS 用户服务可以发现通过 Homebrew 安装的 adb,无需手动修改 LaunchAgent 配置
- 关机时会等正在进行的数据库查询结束再关闭连接,避免 Windows 上测试进程被访问冲突打断
- 模型池里的优先模型可以取消,并且不再显示为聊天框里的选中模型。聊天框只显示专家默认模型或这场对话的手选模型
- 添加云端协同时,权限不足、连接被占用、连到本机或达到条数上限会立刻显示可读错误,不再重试原始关闭帧
Expand Down
9 changes: 9 additions & 0 deletions src/octop/infra/setup/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,14 @@ def render_launchd_plist(runtime: ServiceRuntime) -> str:
if runtime.scope == "system"
else ""
)
# A LaunchAgent does not inherit the interactive shell's Homebrew PATH.
# Keep system binaries first and don't extend the PATH of LaunchDaemons.
path_block = (
" <key>PATH</key>\n"
" <string>/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin:/usr/local/bin</string>\n"
if runtime.scope == "user"
else ""
)
return (
'<?xml version="1.0" encoding="UTF-8"?>\n'
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" '
Expand All @@ -455,6 +463,7 @@ def render_launchd_plist(runtime: ServiceRuntime) -> str:
f" <string>{runtime.home}</string>\n"
" <key>OCTOP_SERVICE_MODE</key>\n"
" <string>launchd</string>\n"
f"{path_block}"
" </dict>\n"
f" <key>WorkingDirectory</key>\n"
f" <string>{runtime.home}</string>\n"
Expand Down
19 changes: 19 additions & 0 deletions tests/unit/infra/setup/test_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import getpass
import json
import os
import plistlib
import shutil
import sys
from dataclasses import replace
Expand Down Expand Up @@ -662,11 +663,29 @@ def test_render_launchd_plist_user_scope_omits_username(tmp_path: Path) -> None:
assert f"<string>{getpass.getuser()}</string>" not in plist # run_as_user should not leak


def test_render_launchd_plist_user_scope_adds_homebrew_to_path(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
monkeypatch.setenv("PATH", str(tmp_path / "installer-only-bin"))
runtime = replace(_runtime(tmp_path), mode="launchd", scope="user")
env = plistlib.loads(render_launchd_plist(runtime).encode())["EnvironmentVariables"]

assert env["PATH"].split(os.pathsep) == [
"/usr/bin",
"/bin",
"/usr/sbin",
"/sbin",
"/opt/homebrew/bin",
"/usr/local/bin",
]


def test_render_launchd_plist_system_scope_includes_username(tmp_path: Path) -> None:
runtime = replace(_runtime(tmp_path), mode="launchd", scope="system")
plist = render_launchd_plist(runtime)
assert "<key>UserName</key>" in plist
assert f"<string>{getpass.getuser()}</string>" in plist
assert "PATH" not in plistlib.loads(plist.encode())["EnvironmentVariables"]


def test_install_service_launchd_user_no_sudo(
Expand Down
Loading