#![cfg(feature = "llm")]
use terraphim_grep::{KgConcept, RetrievedChunk, RlmContext};
use terraphim_router::{
Capability, CostLevel, CostOptimized, Latency, Provider, ProviderType, Router, RoutingContext,
};
fn grep_synthesis_prompt(query: &str, include_answer: bool) -> String {
let chunks = vec![RetrievedChunk {
content: format!("fn handle_{query}() {{}}"),
source: "src/lib.rs".to_string(),
line_start: Some(1),
line_end: Some(1),
relevance_score: 1.0,
haystack: "code",
}];
let concepts = vec![KgConcept {
id: 1,
name: query.to_string(),
display_value: None,
score: 0.9,
}];
let body = RlmContext::new(query.to_string())
.with_chunks(chunks)
.with_concepts(concepts)
.build_prompt();
let tail = if include_answer {
"Synthesise an answer."
} else {
"List the relevant findings."
};
format!("{body}\n\n{tail}\n\nProvide a brief answer based on the context above.")
}
fn llm_kind(model: &str) -> ProviderType {
ProviderType::Llm {
model_id: model.to_string(),
api_endpoint: "https://openrouter.ai/api/v1".to_string(),
}
}
fn fast_provider() -> Provider {
Provider::new(
"fast-summariser",
"Fast Summariser",
llm_kind("liquid/lfm-2.5-1.2b-instruct:free"),
vec![Capability::Explanation, Capability::FastThinking],
)
.with_cost(CostLevel::Cheap)
.with_latency(Latency::Fast)
}
fn code_provider() -> Provider {
Provider::new(
"code-specialist",
"Code Specialist",
llm_kind("qwen/qwen3-coder:free"),
vec![
Capability::CodeGeneration,
Capability::Refactoring,
Capability::Testing,
],
)
.with_cost(CostLevel::Moderate)
.with_latency(Latency::Medium)
}
fn router_with_both_providers() -> Router {
let mut router = Router::new().with_strategy(Box::new(CostOptimized));
router.add_provider(fast_provider());
router.add_provider(code_provider());
router
}
#[test]
fn explanation_query_routes_to_fast_provider() {
let prompt = grep_synthesis_prompt("explain how the retry policy works", false);
let router = router_with_both_providers();
let decision = router
.route(&prompt, &RoutingContext::default())
.expect("router should resolve a provider for an explanation prompt");
assert!(
decision.provider.has_capability(&Capability::Explanation),
"expected provider with Explanation capability, got {} with capabilities {:?}",
decision.provider.id,
decision.provider.capabilities,
);
assert_eq!(
decision.provider.id, "fast-summariser",
"cost-optimised strategy should prefer the Free-tier provider for explanation queries"
);
}
#[test]
fn implementation_query_routes_to_code_provider() {
let prompt = grep_synthesis_prompt(
"implement a function that handles retry with exponential backoff",
true,
);
let mut router =
terraphim_router::Router::new().with_strategy(Box::new(terraphim_router::CapabilityFirst));
router.add_provider(fast_provider());
router.add_provider(code_provider());
let decision = router
.route(&prompt, &RoutingContext::default())
.expect("router should resolve a provider for a code-implementation prompt");
assert!(
decision
.provider
.has_capability(&Capability::CodeGeneration),
"expected CodeGeneration provider for an implementation prompt, got {} with caps {:?}",
decision.provider.id,
decision.provider.capabilities,
);
assert_eq!(decision.provider.id, "code-specialist");
}
#[test]
fn empty_extract_falls_back_without_crashing() {
let prompt = grep_synthesis_prompt("parse_grep_query", false);
let router = router_with_both_providers();
let _ = router
.route(&prompt, &RoutingContext::default())
.expect("router must produce a decision even when keyword extraction is empty");
}