"""Prompt versioning (架构文档 §8.1 Prompt 版本).""" from __future__ import annotations from pathlib import Path import pytest from packages.llm.errors import PromptNotFoundError from packages.llm.prompts import PromptRegistry, parse_prompt_file def test_loads_by_id_and_version(prompts_dir: Path) -> None: registry = PromptRegistry(prompts_dir) v1 = registry.get("agent_chat", "v1") v2 = registry.get("agent_chat", "v2") assert v1.prompt_id == "agent_chat" assert v1.version == "v1" assert v1.ref == "agent_chat@v1" assert v1.system_prefix != v2.system_prefix def test_templates_are_cached_after_first_load(prompts_dir: Path) -> None: registry = PromptRegistry(prompts_dir) assert registry.get("agent_chat", "v1") is registry.get("agent_chat", "v1") def test_missing_prompt_raises(prompts_dir: Path) -> None: registry = PromptRegistry(prompts_dir) with pytest.raises(PromptNotFoundError): registry.get("agent_chat", "v99") def test_available_versions(prompts_dir: Path) -> None: registry = PromptRegistry(prompts_dir) assert registry.available_versions("agent_chat") == ["v1", "v2"] assert registry.available_versions("nope") == [] def test_user_template_rendering() -> None: template = parse_prompt_file( "[system]\n固定前缀\n\n[user]\n用户说:{user_input}\n", prompt_id="x", version="v1" ) assert template.render_user({"user_input": "面试穿什么"}) == "用户说:面试穿什么" def test_missing_variable_is_reported_with_the_prompt_ref() -> None: template = parse_prompt_file( "[system]\n固定前缀\n\n[user]\n{user_input}\n", prompt_id="x", version="v1" ) with pytest.raises(PromptNotFoundError, match="user_input"): template.render_user({}) def test_prompt_without_user_section_renders_empty() -> None: template = parse_prompt_file("[system]\n只有系统前缀\n", prompt_id="x", version="v1") assert template.render_user({"anything": "1"}) == ""