use newt_core::dgx::{DgxConfig, EndpointKind};
use newt_core::Config;
use newt_inference::local::LocalOllamaBackend;
use std::path::Path;
pub async fn run(config_path: Option<&Path>) -> anyhow::Result<()> {
println!("newt doctor — checking backends\n");
let config = match config_path {
Some(p) => Config::load(p)?,
None => Config::resolve()?,
};
println!("Configured backends:");
for backend in &config.backends {
let status = probe_configured_backend(backend).await;
println!(
" {} ({}, {}) — {status}",
backend.name,
backend.endpoint,
backend.kind_label()
);
}
println!("\nConfigured providers:");
if config.providers.is_empty() {
println!(" (none)");
}
for provider in &config.providers {
let status = probe_provider(&provider.command);
println!(
" {} (command: {}) — {status}",
provider.name, provider.command
);
}
println!("\nDGX nodes:");
match &config.dgx {
None => println!(" (none configured)"),
Some(dgx) => probe_dgx(dgx).await,
}
println!("\nEndpoint discovery:");
match LocalOllamaBackend::discover("default").await {
Ok(backend) => println!(" Ollama: reachable at {}", backend.endpoint()),
Err(e) => println!(" Ollama: {e}"),
}
println!("\nShell engine (OCAP):");
let (backend, l3_active) = newt_core::ocap_l3_backend();
match config.shell.as_ref().and_then(|s| s.engine) {
Some(engine) => println!(" configured engine (L2): {engine} (explicit [shell] engine)"),
None => {
let resolved = newt_core::resolved_confined_default();
let why = if resolved == newt_core::ShellEngine::Brush {
"kernel fence enforcing — brush confines dynamic constructs"
} else {
"no per-run kernel fence here — safe-subset refuses dynamic constructs"
};
println!(
" confined default (L2): {resolved} — L3-gated, resolved per run_command ({why})"
);
}
}
println!(" · safe-subset — refuses $(...)/dynamic constructs (portable default)");
println!(
" · host — real /bin/sh in the kernel jail (full grammar; --full-access auto-selects)"
);
println!(
" · brush — carried bash-in-Rust + L2 interceptor (cross-platform; confines restricted exec too; Windows full-access default)"
);
println!(" override per-run: --shell-engine <safe-subset|host|brush>");
println!(
" L3 kernel jail (this platform): {backend} — {}",
if l3_active {
"available"
} else {
"NOT available → a restricted fs grant runs advisory-only (sandbox_kind=None)"
}
);
println!(
" agent-bridle attenuates your full ambient authority into structural OCAP grants; \
--full-access temporarily lifts them."
);
println!("\nMCP servers (newt config + Claude Code config):");
let home = std::env::var_os("HOME").map(std::path::PathBuf::from);
let workspace = std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from("."));
let mcp_toml = newt_core::Config::user_config_dir().map(|d| d.join("mcp.toml"));
let servers = newt_core::mcp::discover(
&config.mcp_servers,
mcp_toml.as_deref(),
home.as_deref(),
&workspace,
);
if servers.is_empty() {
println!(" (none discovered)");
}
let mcp_caveats = config.mcp_probe_caveats(&workspace);
for s in &servers {
match s.transport {
newt_core::mcp::TransportKind::Stdio => {
match newt_mcp_client::connect_stdio(s, &mcp_caveats).await {
Ok(connected) => {
let names: Vec<&str> =
connected.tools.iter().map(|t| t.name.as_str()).collect();
let list = if names.is_empty() {
"(none)".to_string()
} else {
names.join(", ")
};
println!(" {} [stdio] — OK, {} tool(s): {list}", s.name, names.len());
}
Err(e) => println!(" {} [stdio] — ERROR: {e}", s.name),
}
}
newt_core::mcp::TransportKind::Sse | newt_core::mcp::TransportKind::Http => {
let kind = if matches!(s.transport, newt_core::mcp::TransportKind::Sse) {
"sse"
} else {
"http"
};
let url = s.url.clone().unwrap_or_default();
println!(
" {} [{kind}] — {url} (skipped: only stdio is supported in this build)",
s.name
);
}
}
}
Ok(())
}
async fn probe_dgx(dgx: &DgxConfig) {
let active_node_name = dgx.active_node.as_deref();
let active_endpoint = dgx.active_endpoint;
let active_model = dgx.active_model.as_deref().unwrap_or("(none)");
if dgx.nodes.is_empty() {
println!(" (no nodes — using env overrides only)");
}
for node in &dgx.nodes {
let is_active_node = active_node_name.map_or(dgx.nodes.len() == 1, |n| n == node.name);
let node_marker = if is_active_node { " [active node]" } else { "" };
println!(" {}{node_marker}", node.name);
for kind in EndpointKind::ALL {
let Some(url) = node.endpoint(kind) else {
continue;
};
let is_active_ep = is_active_node && kind == active_endpoint;
let active_marker = if is_active_ep { " *" } else { "" };
let status = if kind.is_openai_compatible() {
probe_vllm(url).await
} else {
probe_backend(url).await
};
println!(" {kind} ({url}){active_marker} — {status}");
}
}
match dgx.resolve_endpoint() {
Ok(url) => println!(" Active: {active_model} @ {active_endpoint} → {url}"),
Err(e) => println!(" Active endpoint: unresolved ({e})"),
}
}
async fn probe_configured_backend(backend: &newt_core::config::BackendConfig) -> String {
if backend.kind == Some(newt_core::config::BackendKind::Embedded) {
return "in-process (embedded — no endpoint to probe)".to_string();
}
let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(2))
.build()
.unwrap();
let api_key = backend.resolve_api_key();
if backend.needs_kind_probe() {
return match newt_core::backend_probe::detect_endpoint(
&client,
&backend.endpoint,
api_key.as_deref(),
)
.await
{
Ok(probe) => format!(
"OK (detected {}, {} model(s) served)",
probe.kind.label(),
probe.models.len()
),
Err(e) if e.to_string().starts_with("HTTP ") => e.to_string(),
Err(e) => format!("unreachable: {e}"),
};
}
let kind = backend.kind.expect("needs_kind_probe was false");
match newt_core::backend_probe::api_for(kind)
.list_models(&client, &backend.endpoint, api_key.as_deref())
.await
{
Ok(models) => format!("OK ({} model(s) served)", models.len()),
Err(e) if e.to_string().starts_with("HTTP ") => e.to_string(),
Err(e) => format!("unreachable: {e}"),
}
}
async fn probe_vllm(endpoint: &str) -> String {
let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(2))
.build()
.unwrap();
let url = format!("{}/v1/models", endpoint.trim_end_matches('/'));
match client.get(&url).send().await {
Ok(resp) if resp.status().is_success() => "OK".to_string(),
Ok(resp) => format!("HTTP {}", resp.status()),
Err(e) => format!("unreachable: {e}"),
}
}
async fn probe_backend(endpoint: &str) -> String {
let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(2))
.build()
.unwrap();
let url = format!("{}/api/tags", endpoint.trim_end_matches('/'));
match client.get(&url).send().await {
Ok(resp) if resp.status().is_success() => "OK".to_string(),
Ok(resp) => format!("HTTP {}", resp.status()),
Err(e) => format!("unreachable: {e}"),
}
}
fn probe_provider(command: &str) -> &'static str {
let status = std::process::Command::new(command)
.arg("--version")
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.status();
match status {
Ok(s) if s.success() => "found on PATH",
Ok(_) => "found but exited with error",
Err(_) => "not found on PATH",
}
}
pub fn sign_ocap() -> anyhow::Result<i32> {
use newt_core::ocap_store::{self, PolicyFile, Verdict};
let Some(config_path) = newt_core::Config::user_config_path() else {
anyhow::bail!("cannot resolve the user config directory (~/.newt)");
};
let approve_path = config_path
.with_file_name("ocap")
.join(Verdict::Approve.filename());
let text = match std::fs::read_to_string(&approve_path) {
Ok(t) => t,
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
println!("nothing to sign: {} does not exist", approve_path.display());
return Ok(0);
}
Err(e) => anyhow::bail!("cannot read {}: {e}", approve_path.display()),
};
let mut file = PolicyFile::parse(&text).map_err(|e| anyhow::anyhow!(e))?;
let key_path = newt_identity::default_key_path()?;
let user = newt_identity::load_or_generate(&key_path)?;
let (signed, refused) = ocap_store::sign_approves(
&mut file,
newt_tui::ocap_high_danger_predicate(),
|payload| user.sign(payload).to_bytes(),
);
std::fs::write(
&approve_path,
file.to_toml().map_err(|e| anyhow::anyhow!(e))?,
)
.map_err(|e| anyhow::anyhow!("cannot write {}: {e}", approve_path.display()))?;
println!(
"blessed {}: {signed} entr{} signed with the root key ({})",
approve_path.display(),
if signed == 1 { "y" } else { "ies" },
key_path.display()
);
for r in &refused {
println!(" REFUSED: {r}");
}
let (set, warnings) = ocap_store::load_store(&config_path, Some(user.public().as_bytes()));
for w in &warnings {
println!(" load warning: {w}");
}
let live = set
.files
.get(&Verdict::Approve)
.map(|f| f.exec.len() + f.fs.len() + f.net.len())
.unwrap_or(0);
println!("verified: {live} durable grant(s) live at load");
Ok(if refused.is_empty() { 0 } else { 2 })
}