fix(skill): 优化远程技能安装服务,优化临时工作目录管理
This commit is contained in:
parent
a828d7154b
commit
82d4add70b
@ -3,6 +3,7 @@ from __future__ import annotations
|
|||||||
import asyncio
|
import asyncio
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@ -12,7 +13,6 @@ from yuxi.services.skill_service import import_skill_dir, is_valid_skill_slug
|
|||||||
|
|
||||||
ANSI_ESCAPE_RE = re.compile(r"\x1B\[[0-?]*[ -/]*[@-~]")
|
ANSI_ESCAPE_RE = re.compile(r"\x1B\[[0-?]*[ -/]*[@-~]")
|
||||||
CONTROL_SEQUENCE_RE = re.compile(r"\x1B\][^\x07]*(?:\x07|\x1B\\)|\x1B[\(\)][A-Za-z0-9]")
|
CONTROL_SEQUENCE_RE = re.compile(r"\x1B\][^\x07]*(?:\x07|\x1B\\)|\x1B[\(\)][A-Za-z0-9]")
|
||||||
SKILL_LINE_RE = re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$")
|
|
||||||
CLI_TIMEOUT_SECONDS = 300
|
CLI_TIMEOUT_SECONDS = 300
|
||||||
|
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ def _parse_available_skills(output: str) -> list[dict[str, str]]:
|
|||||||
continue
|
continue
|
||||||
if "Use --skill " in line:
|
if "Use --skill " in line:
|
||||||
break
|
break
|
||||||
if not SKILL_LINE_RE.fullmatch(line):
|
if not is_valid_skill_slug(line):
|
||||||
continue
|
continue
|
||||||
if line in seen:
|
if line in seen:
|
||||||
continue
|
continue
|
||||||
@ -74,10 +74,12 @@ def _parse_available_skills(output: str) -> list[dict[str, str]]:
|
|||||||
continue
|
continue
|
||||||
if "Use --skill " in next_line:
|
if "Use --skill " in next_line:
|
||||||
break
|
break
|
||||||
if SKILL_LINE_RE.fullmatch(next_line):
|
if is_valid_skill_slug(next_line):
|
||||||
break
|
break
|
||||||
if next_line and next_line[0].isalpha():
|
if next_line and next_line[0].isalpha():
|
||||||
description = next_line
|
description = next_line
|
||||||
|
else:
|
||||||
|
continue
|
||||||
break
|
break
|
||||||
|
|
||||||
seen.add(line)
|
seen.add(line)
|
||||||
@ -114,20 +116,27 @@ async def _run_skills_cli(
|
|||||||
return combined
|
return combined
|
||||||
|
|
||||||
|
|
||||||
|
def _create_isolated_workdir() -> tuple[str, dict[str, str], str]:
|
||||||
|
temp_home = tempfile.mkdtemp(prefix=".remote-skills-")
|
||||||
|
env = os.environ.copy()
|
||||||
|
env["HOME"] = temp_home
|
||||||
|
workdir = str(Path(temp_home) / "workspace")
|
||||||
|
Path(workdir).mkdir(parents=True, exist_ok=True)
|
||||||
|
return temp_home, env, workdir
|
||||||
|
|
||||||
|
|
||||||
async def list_remote_skills(source: str) -> list[dict[str, str]]:
|
async def list_remote_skills(source: str) -> list[dict[str, str]]:
|
||||||
normalized_source = _normalize_source(source)
|
normalized_source = _normalize_source(source)
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory(prefix=".remote-skills-") as temp_home:
|
temp_home, env, workdir = _create_isolated_workdir()
|
||||||
env = os.environ.copy()
|
try:
|
||||||
env["HOME"] = temp_home
|
|
||||||
workdir = str(Path(temp_home) / "workspace")
|
|
||||||
Path(workdir).mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
output = await _run_skills_cli(
|
output = await _run_skills_cli(
|
||||||
["npx", "-y", "skills", "add", normalized_source, "--list"],
|
["npx", "-y", "skills", "add", normalized_source, "--list"],
|
||||||
env=env,
|
env=env,
|
||||||
cwd=workdir,
|
cwd=workdir,
|
||||||
)
|
)
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(temp_home, ignore_errors=True)
|
||||||
|
|
||||||
skills = _parse_available_skills(output)
|
skills = _parse_available_skills(output)
|
||||||
if not skills:
|
if not skills:
|
||||||
@ -145,12 +154,8 @@ async def install_remote_skill(
|
|||||||
normalized_source = _normalize_source(source)
|
normalized_source = _normalize_source(source)
|
||||||
normalized_skill = _normalize_skill_name(skill)
|
normalized_skill = _normalize_skill_name(skill)
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory(prefix=".remote-skills-") as temp_home:
|
temp_home, env, workdir = _create_isolated_workdir()
|
||||||
env = os.environ.copy()
|
try:
|
||||||
env["HOME"] = temp_home
|
|
||||||
workdir = str(Path(temp_home) / "workspace")
|
|
||||||
Path(workdir).mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
available_skills = _parse_available_skills(
|
available_skills = _parse_available_skills(
|
||||||
await _run_skills_cli(
|
await _run_skills_cli(
|
||||||
["npx", "-y", "skills", "add", normalized_source, "--list"],
|
["npx", "-y", "skills", "add", normalized_source, "--list"],
|
||||||
@ -188,3 +193,5 @@ async def install_remote_skill(
|
|||||||
source_dir=installed_dir,
|
source_dir=installed_dir,
|
||||||
created_by=created_by,
|
created_by=created_by,
|
||||||
)
|
)
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(temp_home, ignore_errors=True)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user