harn_cli/commands/run/
llm_mock.rs1use std::path::PathBuf;
2
3#[derive(Clone, Debug, Default, PartialEq, Eq)]
4pub enum CliLlmMockMode {
5 #[default]
6 Off,
7 Replay {
8 fixture_path: PathBuf,
9 },
10 Record {
11 fixture_path: PathBuf,
12 },
13}
14
15pub fn install_cli_llm_mock_mode(mode: &CliLlmMockMode) -> Result<(), String> {
16 match mode {
17 CliLlmMockMode::Off => {
18 harn_vm::llm::clear_cli_llm_mock_mode();
19 Ok(())
20 }
21 CliLlmMockMode::Replay { fixture_path } => {
22 let text = std::fs::read_to_string(fixture_path)
23 .map_err(|error| format!("failed to read {}: {error}", fixture_path.display()))?;
24 let fixture = harn_vm::llm::parse_llm_mocks_jsonl(&text).map_err(|error| {
25 format!(
26 "invalid LLM mock fixture in {}: {error}",
27 fixture_path.display()
28 )
29 })?;
30 crate::skill_loader::emit_loader_warnings(&fixture.warnings);
31 harn_vm::llm::clear_cli_llm_mock_mode();
32 harn_vm::llm::install_cli_llm_mock_fixture(fixture);
33 Ok(())
34 }
35 CliLlmMockMode::Record { .. } => {
36 harn_vm::llm::clear_cli_llm_mock_mode();
37 harn_vm::llm::enable_cli_llm_mock_recording();
38 Ok(())
39 }
40 }
41}
42
43pub fn persist_cli_llm_mock_recording(mode: &CliLlmMockMode) -> Result<(), String> {
44 let CliLlmMockMode::Record { fixture_path } = mode else {
45 harn_vm::llm::clear_cli_llm_mock_mode();
46 return Ok(());
47 };
48 let body = harn_vm::llm::serialize_llm_mock_fixture(harn_vm::llm::take_cli_llm_recordings())?;
49 let result = harn_vm::atomic_io::atomic_write(fixture_path, body.as_bytes())
50 .map_err(|error| format!("failed to write {}: {error}", fixture_path.display()));
51 harn_vm::llm::clear_cli_llm_mock_mode();
52 result
53}