Fix #117: include .md prompt files in wheel + handle Windows temp-dir cleanup
Fix 1: Add [tool.setuptools.package-data] to pyproject.toml so that all .md prompt files (generic prompts under skillopt/prompts/ and env-specific prompts under skillopt/envs/*/prompts/) are included in the wheel. Previously pip install from PyPI would fail with FileNotFoundError on first prompt load. Fix 2: Replace TemporaryDirectory context manager with mkdtemp + shutil.rmtree(ignore_errors=True) in claude_backend._run_claude_print. On Windows, the spawned claude/node subprocess still holds a handle on the temp directory when the context manager tries to clean up, causing WinError 32. Manual rmtree with ignore_errors=True works on all Python versions >= 3.10. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -73,6 +73,9 @@ Issues = "https://github.com/microsoft/SkillOpt/issues"
|
|||||||
# skillopt_webui = the Gradio dashboard (installed via the `webui` extra)
|
# skillopt_webui = the Gradio dashboard (installed via the `webui` extra)
|
||||||
include = ["skillopt", "skillopt.*", "skillopt_sleep", "skillopt_sleep.*", "skillopt_webui", "skillopt_webui.*", "scripts*"]
|
include = ["skillopt", "skillopt.*", "skillopt_sleep", "skillopt_sleep.*", "skillopt_webui", "skillopt_webui.*", "scripts*"]
|
||||||
|
|
||||||
|
[tool.setuptools.package-data]
|
||||||
|
"*" = ["*.md"]
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
line-length = 120
|
line-length = 120
|
||||||
target-version = "py310"
|
target-version = "py310"
|
||||||
|
|||||||
@@ -243,7 +243,11 @@ def _assistant_message_schema_wrapper() -> str:
|
|||||||
|
|
||||||
def _run_claude_print(*, system: str, prompt: str, model: str, tools: list[dict[str, Any]] | None, tool_choice: str | dict[str, Any] | None, return_message: bool, timeout: int | None, attachments: list[dict[str, Any]] | None = None) -> tuple[str, dict[str, Any], dict[str, int]]:
|
def _run_claude_print(*, system: str, prompt: str, model: str, tools: list[dict[str, Any]] | None, tool_choice: str | dict[str, Any] | None, return_message: bool, timeout: int | None, attachments: list[dict[str, Any]] | None = None) -> tuple[str, dict[str, Any], dict[str, int]]:
|
||||||
effort = _normalize_reasoning_effort(REASONING_EFFORT)
|
effort = _normalize_reasoning_effort(REASONING_EFFORT)
|
||||||
with tempfile.TemporaryDirectory(prefix="skillopt_claude_") as temp_dir:
|
# Use mkdtemp + manual rmtree to avoid WinError 32 on Windows
|
||||||
|
# where the spawned claude/node subprocess still holds a handle
|
||||||
|
# to the temp directory when the context manager tries to clean up.
|
||||||
|
temp_dir = tempfile.mkdtemp(prefix="skillopt_claude_")
|
||||||
|
try:
|
||||||
copied_attachments = _copy_attachments_to_temp(attachments or [], temp_dir)
|
copied_attachments = _copy_attachments_to_temp(attachments or [], temp_dir)
|
||||||
prompt_for_cli = _append_attachment_instructions(prompt, copied_attachments)
|
prompt_for_cli = _append_attachment_instructions(prompt, copied_attachments)
|
||||||
cmd = [CLAUDE_BIN, "-p", "--output-format", "json", "--permission-mode", CLAUDE_PERMISSION_MODE, "--add-dir", temp_dir]
|
cmd = [CLAUDE_BIN, "-p", "--output-format", "json", "--permission-mode", CLAUDE_PERMISSION_MODE, "--add-dir", temp_dir]
|
||||||
@@ -287,6 +291,8 @@ def _run_claude_print(*, system: str, prompt: str, model: str, tools: list[dict[
|
|||||||
raw_text, result_event = _extract_result(stream)
|
raw_text, result_event = _extract_result(stream)
|
||||||
usage_info = _usage_from_result(result_event)
|
usage_info = _usage_from_result(result_event)
|
||||||
return raw_text, result_event or {}, usage_info
|
return raw_text, result_event or {}, usage_info
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(temp_dir, ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
def _compat_message_from_payload(payload: Any) -> CompatAssistantMessage:
|
def _compat_message_from_payload(payload: Any) -> CompatAssistantMessage:
|
||||||
|
|||||||
Reference in New Issue
Block a user