fix(onboard): Windows npx detection & rename /install-skills to /evoskills (#79)

* fix: improve npx detection on Windows using shutil.which

* fix: rename /install-skills command to /evoskills for consistency
This commit is contained in:
Xi Zhang
2026-03-20 11:42:56 +01:00
committed by GitHub
parent fdafebd47f
commit 372a6272b7
5 changed files with 25 additions and 9 deletions
+3 -3
View File
@@ -127,7 +127,7 @@ _SLASH_COMMANDS = [
("/skills", "List installed skills"),
("/install-skill", "Add a skill from path or GitHub"),
("/uninstall-skill", "Remove an installed skill"),
("/install-skills", "Browse and install skills (optional: /install-skills <tag>)"),
("/evoskills", "Browse and install EvoSkills (optional: /evoskills <tag>)"),
("/mcp", "Manage MCP servers"),
("/channel", "Configure messaging channels"),
("/compact", "Compact conversation to free context"),
@@ -771,8 +771,8 @@ def cmd_interactive(
_cmd_uninstall_skill(name)
continue
if user_input.lower().startswith("/install-skills"):
browse_args = user_input[len("/install-skills") :].strip()
if user_input.lower().startswith("/evoskills"):
browse_args = user_input[len("/evoskills") :].strip()
_cmd_install_skills(browse_args)
continue
+1 -1
View File
@@ -1,4 +1,4 @@
"""Slash commands for skill management: /skills, /install-skill, /uninstall-skill, /install-skills."""
"""Slash commands for skill management: /skills, /install-skill, /uninstall-skill, /evoskills."""
from pathlib import Path
+1 -1
View File
@@ -1,4 +1,4 @@
"""Inline skill browser widget for /install-skills in TUI.
"""Inline skill browser widget for /evoskills in TUI.
Two-phase keyboard-driven widget:
Phase 1 — tag picker (arrow keys + Enter to select, or Esc for all)
@@ -111,9 +111,9 @@ class InstallSkill(Command):
class InstallSkills(Command):
"""Browse and install skills."""
name: ClassVar[str] = "/install-skills"
name: ClassVar[str] = "/evoskills"
description: ClassVar[str] = (
"Browse and install skills (optional: /install-skills <tag>)"
"Browse and install EvoSkills (optional: /evoskills <tag>)"
)
arguments: ClassVar[list[Argument]] = [
Argument(
+18 -2
View File
@@ -7,6 +7,7 @@ workspace settings, and agent parameters. Uses flow-style arrow-key selection UI
from __future__ import annotations
import os
import shutil
import subprocess
import sys
from pathlib import Path
@@ -1421,12 +1422,18 @@ _RECOMMENDED_SKILLS = [
def _check_npx() -> bool:
"""Check if npx is available on the system.
Uses shutil.which() to resolve the executable path, which correctly
finds .cmd/.bat wrappers on Windows (e.g., npx.cmd).
Returns:
True if npx is found and working.
"""
npx = shutil.which("npx")
if not npx:
return False
try:
result = subprocess.run(
["npx", "--version"],
[npx, "--version"],
capture_output=True,
text=True,
timeout=10,
@@ -1460,6 +1467,13 @@ def _detect_node_install_method() -> tuple[str, str]:
except (FileNotFoundError, subprocess.TimeoutExpired):
pass
# Windows: winget (built-in on Win 10+) or chocolatey
if sys.platform == "win32":
if shutil.which("winget"):
return "winget", "winget install OpenJS.NodeJS.LTS"
if shutil.which("choco"):
return "choco", "choco install nodejs-lts -y"
return "manual", "https://nodejs.org"
@@ -1472,9 +1486,11 @@ def _install_node(method: str, command: str) -> bool:
if method == "manual":
return False
parts = command.split()
exe = shutil.which(parts[0]) or parts[0]
try:
proc = subprocess.run(
command.split(),
[exe, *parts[1:]],
capture_output=True,
text=True,
timeout=120,