Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
6 changes: 3 additions & 3 deletions crates/chat-cli/src/cli/chat/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ pub struct Chat {
/// prompt requests permissions to use a tool, unless --trust-all-tools is also used.
#[arg(long)]
pub no_interactive: bool,
/// Start a new conversation and overwrites any previous conversation from this directory.
#[arg(long)]
pub new: bool,
/// Resumes the previous conversation from this directory.
#[arg(short, long)]
pub resume: bool,
/// The first question to ask
pub input: Option<String>,
/// Context profile to use
Expand Down
12 changes: 6 additions & 6 deletions crates/chat-cli/src/cli/chat/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ pub enum Command {
subcommand: Option<PromptsSubcommand>,
},
Usage,
Import {
Load {
path: String,
},
Export {
Save {
path: String,
force: bool,
},
Expand Down Expand Up @@ -818,15 +818,15 @@ impl Command {
}
},
"usage" => Self::Usage,
"import" => {
"load" => {
let Some(path) = parts.get(1) else {
return Err("path is required".to_string());
};
Self::Import {
Self::Load {
path: (*path).to_string(),
}
},
"export" => {
"save" => {
let force = parts.contains(&"-f") || parts.contains(&"--force");
let Some(path) = parts.get(1) else {
return Err("path is required".to_string());
Expand All @@ -835,7 +835,7 @@ impl Command {
if !path.ends_with(".json") {
path.push_str(".json");
}
Self::Export { path, force }
Self::Save { path, force }
},
unknown_command => {
let looks_like_path = {
Expand Down
46 changes: 21 additions & 25 deletions crates/chat-cli/src/cli/chat/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ const WELCOME_TEXT: &str = color_print::cstr! {"<cyan!>
const SMALL_SCREEN_WELCOME_TEXT: &str = color_print::cstr! {"<em>Welcome to <cyan!>Amazon Q</cyan!>!</em>"};
const RESUME_TEXT: &str = color_print::cstr! {"<em>Picking up where we left off...</em>"};

const ROTATING_TIPS: [&str; 11] = [
const ROTATING_TIPS: [&str; 12] = [
color_print::cstr! {"You can resume the last conversation from your current directory by launching with <green!>q chat --resume</green!>"},
color_print::cstr! {"Get notified whenever Q CLI finishes responding. Just run <green!>q settings chat.enableNotifications true</green!>"},
color_print::cstr! {"You can use <green!>/editor</green!> to edit your prompt with a vim-like experience"},
color_print::cstr! {"<green!>/usage</green!> shows you a visual breakdown of your current context window usage"},
Expand Down Expand Up @@ -263,8 +264,8 @@ const HELP_TEXT: &str = color_print::cstr! {"
<em>clear</em> <black!>Clear all files from current context [--global]</black!>
<em>hooks</em> <black!>View and manage context hooks</black!>
<em>/usage</em> <black!>Show current session's context window usage</black!>
<em>/import</em> <black!>Import conversation state from a JSON file</black!>
<em>/export</em> <black!>Export conversation state to a JSON file</black!>
<em>/load</em> <black!>Load conversation state from a JSON file</black!>
<em>/save</em> <black!>Save conversation state to a JSON file</black!>

<cyan,em>MCP:</cyan,em>
<black!>You can now configure the Amazon Q CLI to use MCP servers. \nLearn how: https://docs.aws.amazon.com/en_us/amazonq/latest/qdeveloper-ug/command-line-mcp.html</black!>
Expand Down Expand Up @@ -299,7 +300,7 @@ pub async fn launch_chat(database: &mut Database, telemetry: &TelemetryThread, a
telemetry,
args.input,
args.no_interactive,
args.new,
args.resume,
args.accept_all,
args.profile,
args.trust_all_tools,
Expand All @@ -314,7 +315,7 @@ pub async fn chat(
telemetry: &TelemetryThread,
input: Option<String>,
no_interactive: bool,
new_conversation: bool,
resume_conversation: bool,
accept_all: bool,
profile: Option<String>,
trust_all_tools: bool,
Expand Down Expand Up @@ -443,7 +444,7 @@ pub async fn chat(
input,
InputSource::new(database, prompt_request_sender, prompt_response_receiver)?,
interactive,
new_conversation,
resume_conversation,
client,
|| terminal::window_size().map(|s| s.columns.into()).ok(),
tool_manager,
Expand Down Expand Up @@ -530,7 +531,7 @@ impl ChatContext {
mut input: Option<String>,
input_source: InputSource,
interactive: bool,
new_conversation: bool,
resume_conversation: bool,
client: StreamingClient,
terminal_width_provider: fn() -> Option<usize>,
tool_manager: ToolManager,
Expand All @@ -542,22 +543,7 @@ impl ChatContext {
let output_clone = output.clone();

let mut existing_conversation = false;
let conversation_state = if new_conversation {
let new_state = ConversationState::new(
ctx_clone,
conversation_id,
tool_config,
profile,
Some(output_clone),
tool_manager,
)
.await;

std::env::current_dir()
.ok()
.and_then(|cwd| database.set_conversation_by_path(cwd, &new_state).ok());
new_state
} else {
let conversation_state = if resume_conversation {
let prior = std::env::current_dir()
.ok()
.and_then(|cwd| database.get_conversation_by_path(cwd).ok())
Expand Down Expand Up @@ -585,6 +571,16 @@ impl ChatContext {
)
.await
}
} else {
ConversationState::new(
ctx_clone,
conversation_id,
tool_config,
profile,
Some(output_clone),
tool_manager,
)
.await
};

Ok(Self {
Expand Down Expand Up @@ -2812,7 +2808,7 @@ impl ChatContext {
skip_printing_tools: true,
}
},
Command::Import { path } => {
Command::Load { path } => {
macro_rules! tri {
($v:expr) => {
match $v {
Expand Down Expand Up @@ -2854,7 +2850,7 @@ impl ChatContext {
skip_printing_tools: true,
}
},
Command::Export { path, force } => {
Command::Save { path, force } => {
macro_rules! tri {
($v:expr) => {
match $v {
Expand Down
4 changes: 2 additions & 2 deletions crates/chat-cli/src/cli/chat/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ pub const COMMANDS: &[&str] = &[
"/compact",
"/compact help",
"/usage",
"/import",
"/export",
"/save",
"/load",
];

pub fn generate_prompt(current_profile: Option<&str>, warning: bool) -> String {
Expand Down
32 changes: 22 additions & 10 deletions crates/chat-cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ mod test {
subcommand: Some(CliRootCommands::Chat(Chat {
accept_all: false,
no_interactive: false,
new: false,
resume: false,
input: None,
profile: None,
trust_all_tools: false,
Expand Down Expand Up @@ -408,7 +408,7 @@ mod test {
CliRootCommands::Chat(Chat {
accept_all: false,
no_interactive: false,
new: false,
resume: false,
input: None,
profile: Some("my-profile".to_string()),
trust_all_tools: false,
Expand All @@ -424,7 +424,7 @@ mod test {
CliRootCommands::Chat(Chat {
accept_all: false,
no_interactive: false,
new: false,
resume: false,
input: Some("Hello".to_string()),
profile: Some("my-profile".to_string()),
trust_all_tools: false,
Expand All @@ -440,7 +440,7 @@ mod test {
CliRootCommands::Chat(Chat {
accept_all: true,
no_interactive: false,
new: false,
resume: false,
input: None,
profile: Some("my-profile".to_string()),
trust_all_tools: false,
Expand All @@ -450,13 +450,25 @@ mod test {
}

#[test]
fn test_chat_with_no_interactive_new() {
fn test_chat_with_no_interactive_and_resume() {
assert_parse!(
["chat", "--no-interactive", "--new"],
["chat", "--no-interactive", "--resume"],
CliRootCommands::Chat(Chat {
accept_all: false,
no_interactive: true,
new: true,
resume: true,
input: None,
profile: None,
trust_all_tools: false,
trust_tools: None,
})
);
assert_parse!(
["chat", "--no-interactive", "-r"],
CliRootCommands::Chat(Chat {
accept_all: false,
no_interactive: true,
resume: true,
input: None,
profile: None,
trust_all_tools: false,
Expand All @@ -472,7 +484,7 @@ mod test {
CliRootCommands::Chat(Chat {
accept_all: false,
no_interactive: false,
new: false,
resume: false,
input: None,
profile: None,
trust_all_tools: true,
Expand All @@ -488,7 +500,7 @@ mod test {
CliRootCommands::Chat(Chat {
accept_all: false,
no_interactive: false,
new: false,
resume: false,
input: None,
profile: None,
trust_all_tools: false,
Expand All @@ -504,7 +516,7 @@ mod test {
CliRootCommands::Chat(Chat {
accept_all: false,
no_interactive: false,
new: false,
resume: false,
input: None,
profile: None,
trust_all_tools: false,
Expand Down
10 changes: 6 additions & 4 deletions crates/q_cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,16 +344,18 @@ impl Cli {
CliRootCommands::Telemetry(subcommand) => subcommand.execute().await,
CliRootCommands::Version { changelog } => Self::print_version(changelog),
CliRootCommands::Dashboard => launch_dashboard(false).await,
CliRootCommands::Chat { args } => Self::execute_chat(Some(args)).await,
CliRootCommands::Chat { args } => Self::execute_chat(Some(args), true).await,
CliRootCommands::Inline(subcommand) => subcommand.execute(&cli_context).await,
},
// Root command
None => Self::execute_chat(None).await,
None => Self::execute_chat(None, true).await,
}
}

async fn execute_chat(args: Option<Vec<String>>) -> Result<ExitCode> {
assert_logged_in().await?;
pub async fn execute_chat(args: Option<Vec<String>>, enforce_login: bool) -> Result<ExitCode> {
if enforce_login {
assert_logged_in().await?;
}

let secret_store = SecretStore::new().await.ok();
if let Some(secret_store) = secret_store {
Expand Down
25 changes: 16 additions & 9 deletions crates/q_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,26 @@ fn main() -> Result<ExitCode> {
fig_telemetry::set_dispatch_mode(fig_telemetry::DispatchMode::On);
fig_telemetry::init_global_telemetry_emitter();

let mut args = std::env::args();
let subcommand = args.nth(1);
let multithread = matches!(
std::env::args().nth(1).as_deref(),
subcommand.as_deref(),
Some("init" | "_" | "internal" | "completion" | "hook" | "chat")
);

let runtime = if multithread {
tokio::runtime::Builder::new_multi_thread()
} else {
tokio::runtime::Builder::new_current_thread()
}
.enable_all()
.build()?;

// Hack as clap doesn't expose a custom command help.
if subcommand.as_deref() == Some("chat") && args.any(|arg| ["--help", "-h"].contains(&arg.as_str())) {
runtime.block_on(cli::Cli::execute_chat(Some(vec!["--help".to_owned()]), true))?;
}

let parsed = match cli::Cli::try_parse() {
Ok(cli) => cli,
Err(err) => {
Expand Down Expand Up @@ -58,14 +73,6 @@ fn main() -> Result<ExitCode> {

let verbose = parsed.verbose > 0;

let runtime = if multithread {
tokio::runtime::Builder::new_multi_thread()
} else {
tokio::runtime::Builder::new_current_thread()
}
.enable_all()
.build()?;

let result = runtime.block_on(async {
let result = parsed.execute().await;
fig_telemetry::finish_telemetry().await;
Expand Down
Loading