Files
2026-07-22 13:48:46 +08:00

207 lines
7.6 KiB
Python

import os
import sys
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if PROJECT_ROOT not in sys.path:
sys.path.insert(0, PROJECT_ROOT)
from web_interface.artifacts import extract_latest_artifacts
def test_extract_latest_artifacts_prefers_tagged_files(tmp_path):
workspace_dir = tmp_path / "workspace" / "demo_part"
workspace_dir.mkdir(parents=True)
code_path = workspace_dir / "model.py"
model_path = workspace_dir / "part.stl"
code_path.write_text("print('demo')\n", encoding="utf-8")
model_path.write_text("solid demo\nendsolid demo\n", encoding="utf-8")
messages = [
{
"role": "assistant",
"content": (
"Saved files\n"
"<|code_file|>workspace/demo_part/model.py</|code_file|>\n"
"<|output_file|>workspace/demo_part/part.stl</|output_file|>"
),
}
]
artifacts = extract_latest_artifacts(messages, project_root=tmp_path)
assert artifacts["code_path"] == code_path.resolve(strict=False)
assert artifacts["code_paths"] == [code_path.resolve(strict=False)]
assert artifacts["model_path"] == model_path.resolve(strict=False)
assert artifacts["model_paths"] == [model_path.resolve(strict=False)]
assert artifacts["output_paths"] == [model_path.resolve(strict=False)]
def test_extract_latest_artifacts_accepts_legacy_closing_tags(tmp_path):
workspace_dir = tmp_path / "workspace" / "demo_part"
workspace_dir.mkdir(parents=True)
code_path = workspace_dir / "model.py"
model_path = workspace_dir / "part.stl"
code_path.write_text("print('demo')\n", encoding="utf-8")
model_path.write_text("solid demo\nendsolid demo\n", encoding="utf-8")
messages = [
{
"role": "assistant",
"content": (
"Saved files\n"
"<|code_file|>./demo_part/model.py</|code_file>\n"
"<|output_file|>./demo_part/part.stl</|output_file>"
),
}
]
artifacts = extract_latest_artifacts(messages, project_root=tmp_path / "workspace")
assert artifacts["code_path"] == code_path.resolve(strict=False)
assert artifacts["code_paths"] == [code_path.resolve(strict=False)]
assert artifacts["model_path"] == model_path.resolve(strict=False)
assert artifacts["model_paths"] == [model_path.resolve(strict=False)]
assert artifacts["output_paths"] == [model_path.resolve(strict=False)]
def test_extract_latest_artifacts_falls_back_to_latest_stl_near_model_py(tmp_path):
workspace_dir = tmp_path / "workspace" / "fallback_case"
workspace_dir.mkdir(parents=True)
code_path = workspace_dir / "model.py"
older_stl = workspace_dir / "older.stl"
newer_stl = workspace_dir / "newer.stl"
code_path.write_text("print('demo')\n", encoding="utf-8")
older_stl.write_text("solid older\nendsolid older\n", encoding="utf-8")
newer_stl.write_text("solid newer\nendsolid newer\n", encoding="utf-8")
os.utime(older_stl, (1, 1))
os.utime(newer_stl, (2, 2))
messages = [
{
"role": "assistant",
"content": "<|code_file|>workspace/fallback_case/model.py</|code_file|>",
}
]
artifacts = extract_latest_artifacts(messages, project_root=tmp_path)
assert artifacts["code_path"] == code_path.resolve(strict=False)
assert artifacts["code_paths"] == [code_path.resolve(strict=False)]
assert artifacts["model_path"] == newer_stl.resolve(strict=False)
assert artifacts["model_paths"] == [newer_stl.resolve(strict=False)]
assert artifacts["output_paths"] == []
def test_extract_latest_artifacts_resolves_output_file_relative_to_workspace_root(
tmp_path,
):
workspace_dir = tmp_path / "workspace" / "demo_part"
workspace_dir.mkdir(parents=True)
code_path = workspace_dir / "model.py"
model_path = workspace_dir / "part.stl"
code_path.write_text("print('demo')\n", encoding="utf-8")
model_path.write_text("solid demo\nendsolid demo\n", encoding="utf-8")
messages = [
{
"role": "assistant",
"content": (
"Saved files\n"
"<|code_file|>workspace/demo_part/model.py</|code_file|>\n"
"<|output_file|>./demo_part/part.stl</|output_file|>"
),
}
]
artifacts = extract_latest_artifacts(messages, project_root=tmp_path)
assert artifacts["code_path"] == code_path.resolve(strict=False)
assert artifacts["code_paths"] == [code_path.resolve(strict=False)]
assert artifacts["model_path"] == model_path.resolve(strict=False)
assert artifacts["model_paths"] == [model_path.resolve(strict=False)]
assert artifacts["output_paths"] == [model_path.resolve(strict=False)]
def test_extract_latest_artifacts_resolves_output_file_relative_to_code_dir(tmp_path):
workspace_dir = tmp_path / "workspace" / "demo_part"
workspace_dir.mkdir(parents=True)
code_path = workspace_dir / "model.py"
model_path = workspace_dir / "part.stl"
code_path.write_text("print('demo')\n", encoding="utf-8")
model_path.write_text("solid demo\nendsolid demo\n", encoding="utf-8")
messages = [
{
"role": "assistant",
"content": (
"Saved files\n"
"<|code_file|>workspace/demo_part/model.py</|code_file|>\n"
"<|output_file|>./part.stl</|output_file|>"
),
}
]
artifacts = extract_latest_artifacts(messages, project_root=tmp_path)
assert artifacts["code_path"] == code_path.resolve(strict=False)
assert artifacts["code_paths"] == [code_path.resolve(strict=False)]
assert artifacts["model_path"] == model_path.resolve(strict=False)
assert artifacts["model_paths"] == [model_path.resolve(strict=False)]
assert artifacts["output_paths"] == [model_path.resolve(strict=False)]
def test_extract_latest_artifacts_returns_manual_selection_candidates_in_recency_order(
tmp_path,
):
alpha_dir = tmp_path / "workspace" / "alpha"
beta_dir = tmp_path / "workspace" / "beta"
alpha_dir.mkdir(parents=True)
beta_dir.mkdir(parents=True)
alpha_code = alpha_dir / "model.py"
beta_code = beta_dir / "model.py"
alpha_model = alpha_dir / "alpha.stl"
beta_model = beta_dir / "beta.stl"
alpha_code.write_text("print('alpha')\n", encoding="utf-8")
beta_code.write_text("print('beta')\n", encoding="utf-8")
alpha_model.write_text("solid alpha\nendsolid alpha\n", encoding="utf-8")
beta_model.write_text("solid beta\nendsolid beta\n", encoding="utf-8")
messages = [
{
"role": "assistant",
"content": (
"<|code_file|>workspace/alpha/model.py</|code_file|>\n"
"<|output_file|>workspace/alpha/alpha.stl</|output_file|>"
),
},
{
"role": "assistant",
"content": (
"<|code_file|>workspace/beta/model.py</|code_file|>\n"
"<|output_file|>workspace/beta/beta.stl</|output_file|>"
),
},
]
artifacts = extract_latest_artifacts(messages, project_root=tmp_path)
assert artifacts["code_path"] == beta_code.resolve(strict=False)
assert artifacts["code_paths"] == [
beta_code.resolve(strict=False),
alpha_code.resolve(strict=False),
]
assert artifacts["model_path"] == beta_model.resolve(strict=False)
assert artifacts["model_paths"] == [
beta_model.resolve(strict=False),
alpha_model.resolve(strict=False),
]
assert artifacts["output_paths"] == [
beta_model.resolve(strict=False),
alpha_model.resolve(strict=False),
]