fix(install): avoid greenlet source build on Windows & guide browser tool install

This commit is contained in:
zhayujie
2026-06-15 11:50:41 +08:00
parent d281a34c6f
commit e2cb9e11b0
4 changed files with 47 additions and 3 deletions

View File

@@ -78,12 +78,13 @@ def _is_china_network() -> bool:
def _pip_install(package_spec: str, stream: StreamFn) -> int: def _pip_install(package_spec: str, stream: StreamFn) -> int:
"""Install a package, retrying with --user on permission failure.""" """Install a package, preferring prebuilt wheels; retry with --user on perm error."""
python = sys.executable python = sys.executable
ret = subprocess.call([python, "-m", "pip", "install", package_spec]) base = [python, "-m", "pip", "install", "--prefer-binary"]
ret = subprocess.call(base + [package_spec])
if ret != 0: if ret != 0:
stream(" Retrying with --user flag...", "yellow") stream(" Retrying with --user flag...", "yellow")
ret = subprocess.call([python, "-m", "pip", "install", "--user", package_spec]) ret = subprocess.call(base + ["--user", package_spec])
return ret return ret
@@ -155,6 +156,22 @@ def run_install_browser(
target_version = PLAYWRIGHT_LEGACY_VERSION if legacy_mode else PLAYWRIGHT_VERSION target_version = PLAYWRIGHT_LEGACY_VERSION if legacy_mode else PLAYWRIGHT_VERSION
# Windows-only: greenlet 3.2.x ships no Windows wheel, so pip would build it
# from source (needs MSVC) and fail. Pre-install 3.1.x (has win wheels for
# py3.7-3.13) which still satisfies playwright's greenlet>=3.1.1,<4.
if sys.platform == "win32":
stream("[1/3] Pre-installing greenlet (prebuilt wheel) for Windows...", "yellow")
ret = subprocess.call(
[python, "-m", "pip", "install", "--only-binary=:all:", "greenlet>=3.1.1,<3.2"]
)
if ret != 0:
stream(
" Could not pre-install a prebuilt greenlet wheel.\n"
" playwright may try to build greenlet from source, which needs\n"
" Microsoft C++ Build Tools: https://visualstudio.microsoft.com/visual-cpp-build-tools/",
"yellow",
)
_phase(on_phase, _t("📦 [1/3] 正在安装 Playwright Python 包…", "📦 [1/3] Installing Playwright Python package…")) _phase(on_phase, _t("📦 [1/3] 正在安装 Playwright Python 包…", "📦 [1/3] Installing Playwright Python package…"))
stream("[1/3] Installing playwright Python package...", "yellow") stream("[1/3] Installing playwright Python package...", "yellow")
ret = _pip_install(f"playwright=={target_version}", stream) ret = _pip_install(f"playwright=={target_version}", stream)

View File

@@ -172,6 +172,11 @@ class CloudClient(LinkAIClient):
if key in available_setting and config.get(key) is not None: if key in available_setting and config.get(key) is not None:
local_config[key] = config.get(key) local_config[key] = config.get(key)
# Self-evolution switch: normalize remote value (bool / "Y"/"N" / "true")
# to a real bool so the evolution config parser reads it correctly.
if config.get("self_evolution_enabled") is not None:
local_config["self_evolution_enabled"] = self._to_bool(config.get("self_evolution_enabled"))
# Voice settings # Voice settings
reply_voice_mode = config.get("reply_voice_mode") reply_voice_mode = config.get("reply_voice_mode")
if reply_voice_mode: if reply_voice_mode:
@@ -341,6 +346,20 @@ class CloudClient(LinkAIClient):
except Exception as e: except Exception as e:
logger.warning(f"[CloudClient] Failed to remove weixin credentials: {e}") logger.warning(f"[CloudClient] Failed to remove weixin credentials: {e}")
# ------------------------------------------------------------------
# value helpers
# ------------------------------------------------------------------
@staticmethod
def _to_bool(value) -> bool:
"""Normalize a remote config value to bool (bool / "Y"/"N" / "true"/"1")."""
if isinstance(value, bool):
return value
if isinstance(value, (int, float)):
return value != 0
if isinstance(value, str):
return value.strip().lower() in ("y", "yes", "true", "1", "on")
return False
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# channel credentials helpers # channel credentials helpers
# ------------------------------------------------------------------ # ------------------------------------------------------------------
@@ -855,6 +874,10 @@ def _build_config():
"agent_max_context_turns": local_conf.get("agent_max_context_turns"), "agent_max_context_turns": local_conf.get("agent_max_context_turns"),
"agent_max_context_tokens": local_conf.get("agent_max_context_tokens"), "agent_max_context_tokens": local_conf.get("agent_max_context_tokens"),
"agent_max_steps": local_conf.get("agent_max_steps"), "agent_max_steps": local_conf.get("agent_max_steps"),
# Self-evolution switch reported so the cloud console can reflect state
"self_evolution_enabled": "Y" if local_conf.get("self_evolution_enabled") else "N",
"self_evolution_idle_minutes": local_conf.get("self_evolution_idle_minutes"),
"self_evolution_min_turns": local_conf.get("self_evolution_min_turns"),
"channelType": local_conf.get("channel_type"), "channelType": local_conf.get("channel_type"),
} }

3
run.sh
View File

@@ -980,7 +980,10 @@ start_project() {
echo -e " ${GREEN}./run.sh status${NC} $(t "查看状态" "Check status")" echo -e " ${GREEN}./run.sh status${NC} $(t "查看状态" "Check status")"
echo -e " ${GREEN}./run.sh logs${NC} $(t "查看日志" "View logs")" echo -e " ${GREEN}./run.sh logs${NC} $(t "查看日志" "View logs")"
echo -e " ${GREEN}./run.sh update${NC} $(t "更新并重启" "Update and restart")" echo -e " ${GREEN}./run.sh update${NC} $(t "更新并重启" "Update and restart")"
echo -e " ${GREEN}cow install-browser${NC} $(t "安装浏览器工具" "Install browser tool")"
fi fi
echo ""
echo -e "${YELLOW}$(t "提示:需要让 Agent 浏览网页时,运行 cow install-browser 安装浏览器工具" "Tip: to let the Agent browse the web, run 'cow install-browser' to install the browser tool")${NC}"
echo -e "${CYAN}${BOLD}=========================================${NC}" echo -e "${CYAN}${BOLD}=========================================${NC}"
echo "" echo ""

View File

@@ -748,6 +748,7 @@ function Install-Mode {
# Auto-start after configuration for a true out-of-the-box experience. # Auto-start after configuration for a true out-of-the-box experience.
Write-Host "" Write-Host ""
if ($script:AccessInfo) { Write-Cow $script:AccessInfo } if ($script:AccessInfo) { Write-Cow $script:AccessInfo }
Write-Warn (T "提示:需要让 Agent 浏览网页时,运行 cow install-browser 安装浏览器工具" "Tip: to let the Agent browse the web, run 'cow install-browser' to install the browser tool")
Start-CowAgent Start-CowAgent
} }