Skip to content

Commit 7969fb1

Browse files
authored
adds agent root command for migrate (#2418)
1 parent 880574f commit 7969fb1

File tree

3 files changed

+86
-19
lines changed

3 files changed

+86
-19
lines changed

crates/chat-cli/src/cli/agent/legacy/mod.rs

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ use crate::util::directories;
2525
///
2626
/// Returns [Some] with the newly migrated agents if the migration was performed, [None] if the
2727
/// migration was already done previously.
28-
pub async fn migrate(os: &mut Os) -> eyre::Result<Option<Vec<Agent>>> {
28+
pub async fn migrate(os: &mut Os, force: bool) -> eyre::Result<Option<Vec<Agent>>> {
2929
let has_migrated = os.database.get_has_migrated()?;
30-
if has_migrated.is_some_and(|has_migrated| has_migrated) {
30+
if !force && has_migrated.is_some_and(|has_migrated| has_migrated) {
3131
return Ok(None);
3232
}
3333

@@ -102,22 +102,27 @@ pub async fn migrate(os: &mut Os) -> eyre::Result<Option<Vec<Agent>>> {
102102
}
103103

104104
let labels = vec!["Yes", "No"];
105-
let selection: Option<_> = match Select::with_theme(&crate::util::dialoguer_theme())
106-
.with_prompt("Legacy profiles detected. Would you like to migrate them?")
107-
.items(&labels)
108-
.default(1)
109-
.interact_on_opt(&dialoguer::console::Term::stdout())
110-
{
111-
Ok(sel) => {
112-
let _ = crossterm::execute!(
113-
std::io::stdout(),
114-
crossterm::style::SetForegroundColor(crossterm::style::Color::Magenta)
115-
);
116-
sel
117-
},
118-
// Ctrl‑C -> Err(Interrupted)
119-
Err(dialoguer::Error::IO(ref e)) if e.kind() == std::io::ErrorKind::Interrupted => None,
120-
Err(e) => bail!("Failed to choose an option: {e}"),
105+
let selection: Option<_> = if !force {
106+
match Select::with_theme(&crate::util::dialoguer_theme())
107+
.with_prompt("Legacy profiles detected. Would you like to migrate them?")
108+
.items(&labels)
109+
.default(1)
110+
.interact_on_opt(&dialoguer::console::Term::stdout())
111+
{
112+
Ok(sel) => {
113+
let _ = crossterm::execute!(
114+
std::io::stdout(),
115+
crossterm::style::SetForegroundColor(crossterm::style::Color::Magenta)
116+
);
117+
sel
118+
},
119+
// Ctrl‑C -> Err(Interrupted)
120+
Err(dialoguer::Error::IO(ref e)) if e.kind() == std::io::ErrorKind::Interrupted => None,
121+
Err(e) => bail!("Failed to choose an option: {e}"),
122+
}
123+
} else {
124+
// Yes
125+
Some(0)
121126
};
122127

123128
if selection.is_none() || selection == Some(1) {

crates/chat-cli/src/cli/agent/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ impl Agents {
399399
};
400400

401401
let new_agents = if !skip_migration {
402-
match legacy::migrate(os).await {
402+
match legacy::migrate(os, false).await {
403403
Ok(Some(new_agents)) => {
404404
let migrated_count = new_agents.len();
405405
info!(migrated_count, "Profile migration successful");

crates/chat-cli/src/cli/agent/root_command_args.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use super::{
2121
Agent,
2222
Agents,
2323
McpServerConfig,
24+
legacy,
2425
};
2526
use crate::database::settings::Setting;
2627
use crate::os::Os;
@@ -62,6 +63,13 @@ pub enum AgentSubcommands {
6263
#[arg(long, short)]
6364
path: String,
6465
},
66+
/// Migrate profiles to agent
67+
/// Note that doing this is potentially destructive to agents that are already in the global
68+
/// agent directories
69+
Migrate {
70+
#[arg(long)]
71+
force: bool,
72+
},
6573
}
6674

6775
#[derive(Debug, Clone, PartialEq, Eq, Default, Args)]
@@ -201,7 +209,61 @@ impl AgentArgs {
201209

202210
stderr.flush()?;
203211
},
212+
Some(AgentSubcommands::Migrate { force }) => {
213+
if !force {
214+
let _ = queue!(
215+
stderr,
216+
style::SetForegroundColor(Color::Yellow),
217+
style::Print("WARNING: "),
218+
style::ResetColor,
219+
style::Print(
220+
"manual migrate is potentially destructive to existing agent configs with name collision. Use"
221+
),
222+
style::SetForegroundColor(Color::Cyan),
223+
style::Print(" --force "),
224+
style::ResetColor,
225+
style::Print("to run"),
226+
style::Print("\n"),
227+
);
228+
return Ok(ExitCode::SUCCESS);
229+
}
230+
231+
match legacy::migrate(os, force).await {
232+
Ok(Some(new_agents)) => {
233+
let migrated_count = new_agents.len();
234+
let _ = queue!(
235+
stderr,
236+
style::SetForegroundColor(Color::Green),
237+
style::Print("✓ Success: "),
238+
style::ResetColor,
239+
style::Print(format!(
240+
"Profile migration successful. Migrated {} agent(s)\n",
241+
migrated_count
242+
)),
243+
);
244+
},
245+
Ok(None) => {
246+
let _ = queue!(
247+
stderr,
248+
style::SetForegroundColor(Color::Blue),
249+
style::Print("Info: "),
250+
style::ResetColor,
251+
style::Print("Migration was not performed. Nothing to migrate\n"),
252+
);
253+
},
254+
Err(e) => {
255+
let _ = queue!(
256+
stderr,
257+
style::SetForegroundColor(Color::Red),
258+
style::Print("Error: "),
259+
style::ResetColor,
260+
style::Print(format!("Migration did not happen for the following reason: {e}\n")),
261+
);
262+
},
263+
}
264+
},
204265
}
266+
205267
Ok(ExitCode::SUCCESS)
206268
}
207269
}

0 commit comments

Comments
 (0)