From f2fed60fcbfea9b63694110a98bcd404ca2bd59e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 19 Feb 2026 12:56:46 +0000 Subject: [PATCH 1/2] Initial plan From dfdd8f54a1c39ec33aadad8814212c34c4d6ca4e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 19 Feb 2026 13:02:28 +0000 Subject: [PATCH 2/2] feat(gen): Replace raw stdin loop with rustyline for better interactive input Co-authored-by: yiwang <142937+yiwang@users.noreply.github.com> --- Cargo.lock | 1 + crates/gen/Cargo.toml | 3 +++ crates/gen/src/main.rs | 30 ++++++++++++++++++++++-------- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dea27a9d..c825c4b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5400,6 +5400,7 @@ dependencies = [ "gltf-json", "image", "localgpt-core", + "rustyline", "serde", "serde_json", "shellexpand", diff --git a/crates/gen/Cargo.toml b/crates/gen/Cargo.toml index e9c83595..a0d4e24c 100644 --- a/crates/gen/Cargo.toml +++ b/crates/gen/Cargo.toml @@ -35,6 +35,9 @@ gltf-json = { version = "1", features = ["names"] } # Path resolution shellexpand = { workspace = true } +# CLI line editor +rustyline = "17.0.2" + # Procedural audio (environmental soundscapes) fundsp = "0.20" cpal = "0.15" diff --git a/crates/gen/src/main.rs b/crates/gen/src/main.rs index 16d714b5..29c271fe 100644 --- a/crates/gen/src/main.rs +++ b/crates/gen/src/main.rs @@ -124,7 +124,8 @@ async fn run_agent_loop( use localgpt_core::agent::Agent; use localgpt_core::agent::tools::create_safe_tools; use localgpt_core::memory::MemoryManager; - use std::io::{self, Write}; + use rustyline::DefaultEditor; + use rustyline::error::ReadlineError; use std::sync::Arc; // Set up memory @@ -147,20 +148,33 @@ async fn run_agent_loop( } // Interactive loop - let stdin = io::stdin(); + let mut rl = DefaultEditor::new()?; loop { - print!("> "); - io::stdout().flush()?; + let readline = rl.readline("> "); - let mut input = String::new(); - if stdin.read_line(&mut input)? == 0 { - break; // EOF - } + let input = match readline { + Ok(line) => line, + Err(ReadlineError::Interrupted) => { + println!("^C"); + continue; + } + Err(ReadlineError::Eof) => { + break; // Ctrl+D + } + Err(err) => { + eprintln!("Error: {:?}", err); + break; + } + }; let input = input.trim(); if input.is_empty() { continue; } + + // Add to history + let _ = rl.add_history_entry(input); + if input == "/quit" || input == "/exit" || input == "/q" { break; }