Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions crates/hi-agent/src/agent/lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,18 +108,13 @@ impl crate::Agent {
model: config.model.clone(),
};
// Opt-in: route the skeptic review to a separate OpenAI-compatible
// endpoint (e.g. a local hi-local server) when configured.
let skeptic_provider: Option<Arc<dyn Provider>> =
config.skeptic_endpoint.as_deref().map(|url| {
let key = config
.skeptic_endpoint_key
.clone()
.unwrap_or_else(|| "local".to_string());
Arc::new(hi_ai::OpenAiProvider::new(url.to_string(), key)) as Arc<dyn Provider>
});
// endpoint (e.g. a local hi-local server) when configured. Shared with
// the runtime `/config skeptic-local` toggle so their wiring can't drift.
let skeptic_provider = crate::local_skeptic::build_skeptic_provider(&config);
Ok(Self {
provider,
skeptic_provider,
local_skeptic: None,
config,
runtime,
task_context: None,
Expand Down Expand Up @@ -733,9 +728,11 @@ impl crate::Agent {
self.runtime.background().kill_started_after(before)
}

/// Stop every background process owned by this agent runtime.
/// Stop every background process owned by this agent runtime, plus any
/// auto-managed local skeptic server, on session shutdown.
pub fn kill_background_processes(&self) {
self.runtime.background().kill_all();
self.stop_local_skeptic_server();
}

/// Finalize a turn whose future was cancelled by its frontend. Reconcile
Expand Down
22 changes: 21 additions & 1 deletion crates/hi-agent/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,11 @@ pub enum ConfigArg {
/// `On` forces streaming, `Off` forces resident, `Auto` (the default) lets
/// the loader auto-enable when the model exceeds the memory budget.
MoeStreaming(MoeStreamingMode),
/// `/config skeptic-local <on|off>` — turn the auto-managed local model for
/// the `/goal` skeptic review on or off. `on` detects the machine's backend,
/// downloads a small default review model if needed, and spawns a local
/// server; `off` stops it and restores the prior skeptic settings.
SkepticLocal(bool),
/// Unrecognized option or bad value; carries a usage/error hint.
Invalid(String),
}
Expand Down Expand Up @@ -720,12 +725,27 @@ pub fn parse_config_arg(arg: &str) -> ConfigArg {
}
}
}
"skeptic-local" | "local-skeptic" => match val.to_ascii_lowercase().as_str() {
"" => ConfigArg::Invalid("usage: /config skeptic-local <on|off>".into()),
"on" | "enable" | "enabled" | "1" | "true" | "yes" => ConfigArg::SkepticLocal(true),
"off" | "disable" | "disabled" | "0" | "false" | "no" => ConfigArg::SkepticLocal(false),
_ => ConfigArg::Invalid(format!(
"unknown skeptic-local mode '{val}' — use on or off"
)),
},
other => ConfigArg::Invalid(format!(
"unknown /config option '{other}' — try: show, reasoning <level>, temp <value>, steps <n|auto|off>, moe-streaming <on|off|auto>"
"unknown /config option '{other}' — try: show, reasoning <level>, temp <value>, steps <n|auto|off>, moe-streaming <on|off|auto>, skeptic-local <on|off>"
)),
}
}

/// Whether a `/config` argument is the async `skeptic-local` toggle. The CLI
/// routes this through its async handler (it may download a model and spawn a
/// server) rather than the synchronous `/config` path.
pub fn config_is_skeptic_local(arg: &str) -> bool {
matches!(parse_config_arg(arg), ConfigArg::SkepticLocal(_))
}

fn read_only_macro_prompt(kind: &str, topic: &str) -> String {
let topic = topic.trim();
let topic = if topic.is_empty() {
Expand Down
7 changes: 7 additions & 0 deletions crates/hi-agent/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod context_index;
mod decision;
mod goal;
mod heuristics;
pub mod local_skeptic;
mod memory;
mod outcome;
mod prompt;
Expand Down Expand Up @@ -37,6 +38,7 @@ pub use config::{
};
pub use heuristics::humanize_count;
pub use hi_tools::{PlanStatus, PlanStep};
pub use local_skeptic::LocalSkepticOutcome;
pub use memory::{
AnnotatedBullet, global_memory_file, memory_file, read_global_memory, read_memory,
read_project_annotated, should_distill_memory,
Expand Down Expand Up @@ -557,6 +559,11 @@ pub struct Agent {
/// as it always has. Lets the frequent, fail-open review loop run on a local
/// model while the driver stays on the session model.
pub(crate) skeptic_provider: Option<Arc<dyn Provider>>,
/// Session state for an auto-managed local skeptic server started by
/// `/config skeptic-local on` (`None` when off). Held so the server can be
/// stopped, the prior skeptic settings restored, and the process killed on
/// session shutdown.
pub(crate) local_skeptic: Option<crate::local_skeptic::LocalSkepticState>,
pub(crate) config: AgentConfig,
pub(crate) runtime: WorkspaceRuntime,
/// Per-turn ranked repository data and scoped instructions.
Expand Down
Loading
Loading