use anyhow::Result;
use clap::Args;
use crate::integrate::{Host, IntegrationRegistry, deregister_integration, do_undo};
#[derive(Args, Debug)]
pub(crate) struct UnintegrateArgs {
pub hosts: Vec<String>,
#[arg(long)]
pub all: bool,
#[arg(long)]
pub dry_run: bool,
}
pub(crate) fn run(args: UnintegrateArgs) -> Result<()> {
let reg = IntegrationRegistry::load();
if reg.hosts.is_empty() && args.hosts.is_empty() && !args.all {
println!("No integrations recorded in ~/.mnemglobal/integrations.toml.");
println!("Nothing to remove.");
return Ok(());
}
let selected: Vec<Host> = if args.all {
if reg.hosts.is_empty() {
println!("No integrations recorded. Nothing to remove.");
return Ok(());
}
reg.hosts
.iter()
.filter_map(|r| Host::parse(&r.slug))
.collect()
} else if !args.hosts.is_empty() {
let mut out = Vec::new();
for name in &args.hosts {
match Host::parse(name) {
Some(h) => out.push(h),
None => {
eprintln!("unintegrate: unknown host {:?}", name);
eprintln!(
" Valid hosts: {}",
Host::all()
.iter()
.map(|h| h.slug())
.collect::<Vec<_>>()
.join(", ")
);
}
}
}
if out.is_empty() {
return Ok(());
}
out
} else {
interactive_select(®)?
};
if selected.is_empty() {
println!("Nothing selected.");
return Ok(());
}
println!(
"Removing mnem wiring{}:",
if args.dry_run { " (dry-run)" } else { "" }
);
for host in &selected {
do_undo(*host, args.dry_run)?;
if !args.dry_run {
deregister_integration(*host);
}
}
if !args.dry_run {
println!();
println!("Done. Restart each agent host you modified.");
}
Ok(())
}
fn interactive_select(reg: &IntegrationRegistry) -> Result<Vec<Host>> {
use anyhow::Context as _;
use dialoguer::{MultiSelect, theme::ColorfulTheme};
if reg.hosts.is_empty() {
println!("No integrations recorded in ~/.mnemglobal/integrations.toml.");
println!("If you integrated before this version, use a named host:");
let slugs = Host::all()
.iter()
.map(|h| h.slug())
.collect::<Vec<_>>()
.join(", ");
println!(" mnem unintegrate <host> (hosts: {slugs})");
return Ok(vec![]);
}
let entries: Vec<(Host, String)> = reg
.hosts
.iter()
.filter_map(|r| {
Host::parse(&r.slug).map(|h| {
let components = if r.components.is_empty() {
"mcp".to_string()
} else {
r.components.join(", ")
};
(h, format!("{} ({})", r.display, components))
})
})
.collect();
println!("mnem unintegrate - remove mnem wiring from agent hosts\n");
let items: Vec<&str> = entries.iter().map(|(_, s)| s.as_str()).collect();
let defaults: Vec<bool> = vec![true; items.len()];
let picks = MultiSelect::with_theme(&ColorfulTheme::default())
.with_prompt("Which to remove? (space to toggle, enter to confirm)")
.items(&items)
.defaults(&defaults)
.interact()
.context("interactive prompt failed")?;
Ok(picks.into_iter().map(|i| entries[i].0).collect())
}