|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
| 3 | +import json |
| 4 | +import os |
3 | 5 | from pathlib import Path |
4 | 6 |
|
5 | 7 | from verifiers.scripts import setup |
@@ -101,3 +103,186 @@ def test_sync_prime_skills_creates_dot_prime_tree(tmp_path: Path, monkeypatch) - |
101 | 103 | ".prime/skills/brainstorm/SKILL.md", |
102 | 104 | ), |
103 | 105 | ] |
| 106 | + |
| 107 | + |
| 108 | +def test_prepare_agent_skill_dirs_materializes_skills_from_prime( |
| 109 | + tmp_path: Path, monkeypatch |
| 110 | +) -> None: |
| 111 | + monkeypatch.chdir(tmp_path) |
| 112 | + monkeypatch.setattr(setup, "LAB_SKILLS", ["create-environments", "brainstorm"]) |
| 113 | + |
| 114 | + for skill_name in setup.LAB_SKILLS: |
| 115 | + skill_dir = tmp_path / ".prime" / "skills" / skill_name |
| 116 | + skill_dir.mkdir(parents=True, exist_ok=True) |
| 117 | + (skill_dir / "SKILL.md").write_text(f"{skill_name}\n") |
| 118 | + |
| 119 | + setup._prepare_agent_skill_dirs(["codex"]) |
| 120 | + |
| 121 | + for skill_name in setup.LAB_SKILLS: |
| 122 | + source = tmp_path / ".prime" / "skills" / skill_name |
| 123 | + target = tmp_path / ".codex" / "skills" / skill_name |
| 124 | + assert target.exists() |
| 125 | + assert (target / "SKILL.md").exists() |
| 126 | + if target.is_symlink(): |
| 127 | + assert target.resolve() == source.resolve() |
| 128 | + |
| 129 | + |
| 130 | +def test_prepare_agent_skill_dirs_is_safe_with_existing_links( |
| 131 | + tmp_path: Path, monkeypatch |
| 132 | +) -> None: |
| 133 | + monkeypatch.chdir(tmp_path) |
| 134 | + monkeypatch.setattr(setup, "LAB_SKILLS", ["create-environments"]) |
| 135 | + |
| 136 | + source = tmp_path / ".prime" / "skills" / "create-environments" |
| 137 | + source.mkdir(parents=True, exist_ok=True) |
| 138 | + (source / "SKILL.md").write_text("create-environments\n") |
| 139 | + |
| 140 | + target = tmp_path / ".codex" / "skills" / "create-environments" |
| 141 | + target.parent.mkdir(parents=True, exist_ok=True) |
| 142 | + target.symlink_to( |
| 143 | + os.path.relpath(source, start=target.parent), |
| 144 | + target_is_directory=True, |
| 145 | + ) |
| 146 | + |
| 147 | + setup._prepare_agent_skill_dirs(["codex"]) |
| 148 | + |
| 149 | + assert target.is_symlink() |
| 150 | + assert target.resolve() == source.resolve() |
| 151 | + assert (target / "SKILL.md").exists() |
| 152 | + |
| 153 | + |
| 154 | +def test_prepare_agent_skill_dirs_uses_mapped_root_for_amp( |
| 155 | + tmp_path: Path, monkeypatch |
| 156 | +) -> None: |
| 157 | + monkeypatch.chdir(tmp_path) |
| 158 | + monkeypatch.setattr(setup, "LAB_SKILLS", ["create-environments"]) |
| 159 | + |
| 160 | + source = tmp_path / ".prime" / "skills" / "create-environments" |
| 161 | + source.mkdir(parents=True, exist_ok=True) |
| 162 | + (source / "SKILL.md").write_text("create-environments\n") |
| 163 | + |
| 164 | + setup._prepare_agent_skill_dirs(["amp"]) |
| 165 | + |
| 166 | + assert ( |
| 167 | + tmp_path / ".agents" / "skills" / "create-environments" / "SKILL.md" |
| 168 | + ).exists() |
| 169 | + assert not (tmp_path / ".amp" / "skills").exists() |
| 170 | + |
| 171 | + |
| 172 | +def test_prepare_agent_skill_dirs_supports_skill_name_mapping( |
| 173 | + tmp_path: Path, monkeypatch |
| 174 | +) -> None: |
| 175 | + monkeypatch.chdir(tmp_path) |
| 176 | + monkeypatch.setattr(setup, "LAB_SKILLS", ["create-environments"]) |
| 177 | + monkeypatch.setattr( |
| 178 | + setup, |
| 179 | + "AGENT_SKILL_NAME_MAP", |
| 180 | + {"amp": {"create-environments": "create-envs"}}, |
| 181 | + ) |
| 182 | + |
| 183 | + source = tmp_path / ".prime" / "skills" / "create-environments" |
| 184 | + source.mkdir(parents=True, exist_ok=True) |
| 185 | + (source / "SKILL.md").write_text("create-environments\n") |
| 186 | + |
| 187 | + setup._prepare_agent_skill_dirs(["amp"]) |
| 188 | + |
| 189 | + assert (tmp_path / ".agents" / "skills" / "create-envs" / "SKILL.md").exists() |
| 190 | + assert not (tmp_path / ".agents" / "skills" / "create-environments").exists() |
| 191 | + |
| 192 | + |
| 193 | +def test_run_setup_prints_post_setup_call_to_action( |
| 194 | + tmp_path: Path, monkeypatch, capsys |
| 195 | +) -> None: |
| 196 | + monkeypatch.chdir(tmp_path) |
| 197 | + |
| 198 | + monkeypatch.setattr(setup.wget, "download", _fake_download_factory([])) |
| 199 | + monkeypatch.setattr(setup, "download_configs", lambda *_: None) |
| 200 | + monkeypatch.setattr(setup, "sync_prime_skills", lambda: None) |
| 201 | + |
| 202 | + setup.run_setup(skip_install=True, skip_agents_md=True) |
| 203 | + |
| 204 | + output = capsys.readouterr().out |
| 205 | + assert "Prepared .codex/skills" in output |
| 206 | + assert output.index("Prepared .codex/skills") < output.index("get started") |
| 207 | + assert "get started" in output |
| 208 | + assert "quick commands" in output |
| 209 | + assert "ask codex" in output |
| 210 | + assert "example prompt" not in output |
| 211 | + assert 'ask codex: "I want to train a model for my task domain.' not in output |
| 212 | + assert "idea -> environment -> eval -> training" in output |
| 213 | + assert "prime env init my-env" in output |
| 214 | + assert "prime env install my-env" not in output |
| 215 | + assert "prime eval run my-env -m gpt-5-nano -n 5" in output |
| 216 | + assert "prime eval tui" in output |
| 217 | + assert "prime rl run configs/rl/wiki-search.toml" in output |
| 218 | + assert "prime gepa run my-env -m gpt-5-nano" in output |
| 219 | + |
| 220 | + |
| 221 | +def test_run_setup_prints_prime_rl_post_setup_call_to_action( |
| 222 | + tmp_path: Path, monkeypatch, capsys |
| 223 | +) -> None: |
| 224 | + monkeypatch.chdir(tmp_path) |
| 225 | + |
| 226 | + monkeypatch.setattr(setup.wget, "download", _fake_download_factory([])) |
| 227 | + monkeypatch.setattr(setup, "download_configs", lambda *_: None) |
| 228 | + monkeypatch.setattr(setup, "sync_prime_skills", lambda: None) |
| 229 | + monkeypatch.setattr(setup, "install_prime_rl", lambda: None) |
| 230 | + monkeypatch.setattr(setup, "install_environments_to_prime_rl", lambda: None) |
| 231 | + |
| 232 | + setup.run_setup(skip_install=True, skip_agents_md=True, prime_rl=True) |
| 233 | + |
| 234 | + output = capsys.readouterr().out |
| 235 | + assert "get started" in output |
| 236 | + assert "quick commands" in output |
| 237 | + assert "ask codex" in output |
| 238 | + assert "example prompt" not in output |
| 239 | + assert "prime env install my-env" not in output |
| 240 | + assert "uv run prime-rl configs/prime-rl/wiki-search.toml" in output |
| 241 | + assert "prime rl run configs/rl/wiki-search.toml" not in output |
| 242 | + |
| 243 | + |
| 244 | +def test_run_setup_persists_lab_choices_metadata(tmp_path: Path, monkeypatch) -> None: |
| 245 | + monkeypatch.chdir(tmp_path) |
| 246 | + |
| 247 | + monkeypatch.setattr(setup.wget, "download", _fake_download_factory([])) |
| 248 | + monkeypatch.setattr(setup, "download_configs", lambda *_: None) |
| 249 | + monkeypatch.setattr(setup, "sync_prime_skills", lambda: None) |
| 250 | + |
| 251 | + setup.run_setup( |
| 252 | + skip_install=True, |
| 253 | + skip_agents_md=True, |
| 254 | + agents="codex,cursor,codex", |
| 255 | + no_interactive=True, |
| 256 | + ) |
| 257 | + |
| 258 | + metadata_path = tmp_path / ".prime" / "lab.json" |
| 259 | + assert metadata_path.exists() |
| 260 | + metadata = json.loads(metadata_path.read_text()) |
| 261 | + assert metadata["setup_source"] == "prime lab setup" |
| 262 | + assert metadata["choices"] == { |
| 263 | + "agents": ["codex", "cursor"], |
| 264 | + "primary_agent": "codex", |
| 265 | + "use_multiple_agents": True, |
| 266 | + } |
| 267 | + |
| 268 | + |
| 269 | +def test_run_setup_persists_default_lab_choices_metadata( |
| 270 | + tmp_path: Path, monkeypatch |
| 271 | +) -> None: |
| 272 | + monkeypatch.chdir(tmp_path) |
| 273 | + |
| 274 | + monkeypatch.setattr(setup.wget, "download", _fake_download_factory([])) |
| 275 | + monkeypatch.setattr(setup, "download_configs", lambda *_: None) |
| 276 | + monkeypatch.setattr(setup, "sync_prime_skills", lambda: None) |
| 277 | + |
| 278 | + setup.run_setup(skip_install=True, skip_agents_md=True, no_interactive=True) |
| 279 | + |
| 280 | + metadata_path = tmp_path / ".prime" / "lab.json" |
| 281 | + assert metadata_path.exists() |
| 282 | + metadata = json.loads(metadata_path.read_text()) |
| 283 | + assert metadata["setup_source"] == "prime lab setup" |
| 284 | + assert metadata["choices"] == { |
| 285 | + "agents": ["codex"], |
| 286 | + "primary_agent": "codex", |
| 287 | + "use_multiple_agents": False, |
| 288 | + } |
0 commit comments