use anyhow::Result;
use async_trait::async_trait;
use crate::config::Config;
use crate::llm::{review_diff, ReviewResult};
use crate::providers::{PrMeta, Provider};
use crate::review::run_agentic;
pub struct ReviewContext<'a> {
pub client: &'a reqwest::Client,
pub cfg: &'a Config,
pub provider: &'a Provider,
pub repo: &'a str,
pub meta: &'a PrMeta,
pub diff: &'a str,
pub omitted_note: Option<&'a str>,
pub structural_context: Option<&'a str>,
}
#[async_trait]
pub trait ReviewBackend: Send + Sync {
async fn review(&self, ctx: &ReviewContext<'_>) -> Result<ReviewResult>;
}
pub struct OpenRouterBackend;
#[async_trait]
impl ReviewBackend for OpenRouterBackend {
async fn review(&self, ctx: &ReviewContext<'_>) -> Result<ReviewResult> {
if ctx.cfg.agentic {
match run_agentic(
ctx.provider,
ctx.client,
ctx.cfg,
ctx.meta,
ctx.diff,
ctx.omitted_note,
ctx.structural_context,
ctx.repo,
)
.await
{
Ok(r) => Ok(r),
Err(e) => {
tracing::warn!(
"agentic review failed for {}#{} ({e:#}); falling back to diff-only",
ctx.repo,
ctx.meta.pr,
);
review_diff(
ctx.client,
ctx.cfg,
ctx.meta,
ctx.diff,
ctx.omitted_note.map(str::to_string),
ctx.structural_context,
)
.await
}
}
} else {
review_diff(
ctx.client,
ctx.cfg,
ctx.meta,
ctx.diff,
ctx.omitted_note.map(str::to_string),
ctx.structural_context,
)
.await
}
}
}