1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//! Non-hot-path LLM dispatch via the user's installed agent CLI.
//!
//! Lets DiffLore make occasional LLM calls (candidate-name extraction,
//! `plan_pr` secondary judgment, etc.) without requiring a BYOK provider —
//! most users have no LLM key configured at install time. If the user is
//! already running a gate4agent-supported CLI (Claude Code, Codex, Gemini CLI),
//! we call it through gate4agent for the gate call: the CLI handles auth via the
//! user's existing session, and dispatch stays off the hot path so its latency
//! only affects best-effort gates.
//!
//! ## Surface
//!
//! One public async function:
//!
//! ```rust,ignore
//! use std::time::Duration;
//! use difflore_cli::agent_exec::{AgentKind, dispatch_gate};
//!
//! async fn example() {
//! let result = dispatch_gate(
//! AgentKind::ClaudeCode,
//! "Rate this PR description 1-5: ...",
//! Duration::from_secs(30),
//! ).await;
//! if !result.errored {
//! println!("model said: {}", result.stdout);
//! }
//! }
//! ```
//!
//! ## Non-goals
//!
//! - Not a streaming API. The use cases are short ratings / yes-no
//! gates / JSON envelopes — buffering the whole response is fine and
//! simpler than wiring a streaming reader.
//! - Not a BYOK provider replacement. The existing
//! `crate::commands::providers` flow stays the canonical path for
//! power users who want per-model latency / cost knobs. Gate-runner-
//! style CLI dispatch is the "no key required" fallback.
pub use ;
use Duration;
/// Dispatch a single LLM call to whichever agent CLI matches `agent`.
///
/// Never panics — even on a missing binary the result is errored, so callers
/// can downgrade a failed gate to "skip, don't block". `time_budget` is
/// enforced via `tokio::time::timeout`; timed-out sessions are killed through
/// gate4agent.
pub async