use phi_core::agents::system_prompt::*;
use std::collections::HashMap;
use std::path::Path;
#[test]
fn test_prompt_block_def_ordering() {
let strategy = CustomPromptStrategy {
blocks: vec![
PromptBlockDef {
name: "c".into(),
order: 2,
max_length: 1000,
},
PromptBlockDef {
name: "a".into(),
order: 0,
max_length: 1000,
},
PromptBlockDef {
name: "b".into(),
order: 1,
max_length: 1000,
},
],
};
let mut blocks = HashMap::new();
blocks.insert("a".into(), "ALPHA".into());
blocks.insert("b".into(), "BRAVO".into());
blocks.insert("c".into(), "CHARLIE".into());
let prompt = SystemPrompt {
id: "test".into(),
description: None,
strategy_ref: "test".into(),
blocks,
};
let result = prompt.compose(&strategy, Path::new(".")).unwrap();
assert_eq!(result, "ALPHA\n\nBRAVO\n\nCHARLIE");
}
#[test]
fn test_prompt_block_max_length_truncation() {
let strategy = CustomPromptStrategy {
blocks: vec![PromptBlockDef {
name: "a".into(),
order: 0,
max_length: 5,
}],
};
let mut blocks = HashMap::new();
blocks.insert("a".into(), "hello world".into());
let prompt = SystemPrompt {
id: "test".into(),
description: None,
strategy_ref: "test".into(),
blocks,
};
let result = prompt.compose(&strategy, Path::new(".")).unwrap();
assert_eq!(result, "hello");
}
#[test]
fn test_system_prompt_compose_from_strategy() {
let strategy = AgentPromptStrategy::default();
let mut blocks = HashMap::new();
blocks.insert("identity".into(), "You are Phi.".into());
blocks.insert("instructions".into(), "Write clean code.".into());
let prompt = SystemPrompt {
id: "agent-prompt".into(),
description: Some("Agent prompt".into()),
strategy_ref: "agent_layout".into(),
blocks,
};
let result = prompt.compose(&strategy, Path::new(".")).unwrap();
assert!(result.contains("You are Phi."), "should contain identity");
assert!(
result.contains("Write clean code."),
"should contain instructions"
);
let identity_pos = result.find("You are Phi.").unwrap();
let instructions_pos = result.find("Write clean code.").unwrap();
assert!(
identity_pos < instructions_pos,
"identity should appear before instructions"
);
}
#[test]
fn test_system_prompt_missing_block_skipped() {
let strategy = CustomPromptStrategy {
blocks: vec![
PromptBlockDef {
name: "a".into(),
order: 0,
max_length: 1000,
},
PromptBlockDef {
name: "b".into(),
order: 1,
max_length: 1000,
},
PromptBlockDef {
name: "c".into(),
order: 2,
max_length: 1000,
},
],
};
let mut blocks = HashMap::new();
blocks.insert("a".into(), "first".into());
blocks.insert("c".into(), "third".into());
let prompt = SystemPrompt {
id: "test".into(),
description: None,
strategy_ref: "test".into(),
blocks,
};
let result = prompt.compose(&strategy, Path::new(".")).unwrap();
assert_eq!(result, "first\n\nthird");
}
#[test]
fn test_system_prompt_file_resolution_relative() {
let dir = tempfile::tempdir().unwrap();
let file_path = dir.path().join("filename.txt");
std::fs::write(&file_path, "file content").unwrap();
let strategy = CustomPromptStrategy {
blocks: vec![PromptBlockDef {
name: "a".into(),
order: 0,
max_length: 1000,
}],
};
let mut blocks = HashMap::new();
blocks.insert("a".into(), "file:filename.txt".into());
let prompt = SystemPrompt {
id: "test".into(),
description: None,
strategy_ref: "test".into(),
blocks,
};
let result = prompt.compose(&strategy, dir.path()).unwrap();
assert_eq!(result, "file content");
}
#[test]
fn test_system_prompt_file_resolution_absolute() {
let dir = tempfile::tempdir().unwrap();
let abs_path = dir.path().join("phi_test_prompt_abs.txt");
std::fs::write(&abs_path, "absolute file content").unwrap();
let strategy = CustomPromptStrategy {
blocks: vec![PromptBlockDef {
name: "a".into(),
order: 0,
max_length: 1000,
}],
};
let file_ref = format!("file:{}", abs_path.display());
let mut blocks = HashMap::new();
blocks.insert("a".into(), file_ref);
let prompt = SystemPrompt {
id: "test".into(),
description: None,
strategy_ref: "test".into(),
blocks,
};
let result = prompt.compose(&strategy, Path::new(".")).unwrap();
assert_eq!(result, "absolute file content");
}
#[test]
fn test_system_prompt_file_not_found_error() {
let strategy = CustomPromptStrategy {
blocks: vec![PromptBlockDef {
name: "a".into(),
order: 0,
max_length: 1000,
}],
};
let mut blocks = HashMap::new();
blocks.insert("a".into(), "file:nonexistent.txt".into());
let prompt = SystemPrompt {
id: "test".into(),
description: None,
strategy_ref: "test".into(),
blocks,
};
let result = prompt.compose(&strategy, Path::new("."));
assert!(result.is_err(), "should error on missing file");
}
#[test]
fn test_agent_prompt_strategy_builtin() {
let s = AgentPromptStrategy::default();
let defs = s.block_defs();
assert_eq!(defs.len(), 4);
assert_eq!(defs[0].name, "identity");
assert_eq!(defs[0].order, 0);
assert_eq!(defs[1].name, "instructions");
assert_eq!(defs[1].order, 1);
assert_eq!(defs[2].name, "tools");
assert_eq!(defs[2].order, 2);
assert_eq!(defs[3].name, "constraints");
assert_eq!(defs[3].order, 3);
}
#[test]
fn test_minimal_prompt_strategy_builtin() {
let s = MinimalPromptStrategy::default();
let defs = s.block_defs();
assert_eq!(defs.len(), 2);
assert_eq!(defs[0].name, "identity");
assert_eq!(defs[0].order, 0);
assert_eq!(defs[1].name, "task");
assert_eq!(defs[1].order, 1);
}