Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 10 additions & 2 deletions crates/chat-cli/src/cli/chat/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ use tools::ToolsArgs;
use crate::cli::chat::cli::subscribe::SubscribeArgs;
use crate::cli::chat::cli::usage::UsageArgs;
use crate::cli::chat::consts::AGENT_MIGRATION_DOC_URL;
use crate::cli::chat::{ChatError, ChatSession, ChatState, EXTRA_HELP};
use crate::cli::chat::{
ChatError,
ChatSession,
ChatState,
EXTRA_HELP,
};
use crate::cli::issue;
use crate::os::Os;

Expand Down Expand Up @@ -93,7 +98,10 @@ impl SlashCommand {
Self::Clear(args) => args.execute(session).await,
Self::Agent(subcommand) => subcommand.execute(os, session).await,
Self::Profile => {
use crossterm::{execute, style};
use crossterm::{
execute,
style,
};
execute!(
session.stderr,
style::SetForegroundColor(style::Color::Yellow),
Expand Down
15 changes: 10 additions & 5 deletions crates/chat-cli/src/cli/chat/cli/tangent.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
use clap::Args;
use crossterm::execute;
use crossterm::style::{self, Color};
use crossterm::style::{
self,
Color,
};

use crate::cli::chat::{ChatError, ChatSession, ChatState};
use crate::cli::chat::{
ChatError,
ChatSession,
ChatState,
};
use crate::os::Os;

#[derive(Debug, PartialEq, Args)]
Expand Down Expand Up @@ -52,9 +59,7 @@ impl TangentArgs {
style::Print("/tangent"),
style::SetForegroundColor(Color::DarkGrey),
style::Print(" to restore the conversation later.\n"),
style::Print(
"Note: this functionality is experimental and may change or be removed in the future.\n"
),
style::Print("Note: this functionality is experimental and may change or be removed in the future.\n"),
style::SetForegroundColor(Color::Reset)
)?;
}
Expand Down
20 changes: 16 additions & 4 deletions crates/chat-cli/src/cli/chat/conversation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1360,8 +1360,14 @@ mod tests {
assert!(!conversation.is_in_tangent_mode());

// Add some main conversation history
conversation.set_next_user_message("main conversation".to_string()).await;
conversation.push_assistant_message(&mut os, AssistantMessage::new_response(None, "main response".to_string()), None);
conversation
.set_next_user_message("main conversation".to_string())
.await;
conversation.push_assistant_message(
&mut os,
AssistantMessage::new_response(None, "main response".to_string()),
None,
);
conversation.transcript.push_back("main transcript".to_string());

let main_history_len = conversation.history.len();
Expand All @@ -1377,8 +1383,14 @@ mod tests {
assert!(conversation.next_message.is_none());

// Add tangent conversation
conversation.set_next_user_message("tangent conversation".to_string()).await;
conversation.push_assistant_message(&mut os, AssistantMessage::new_response(None, "tangent response".to_string()), None);
conversation
.set_next_user_message("tangent conversation".to_string())
.await;
conversation.push_assistant_message(
&mut os,
AssistantMessage::new_response(None, "tangent response".to_string()),
None,
);

// During tangent mode, history should have grown
assert_eq!(conversation.history.len(), main_history_len + 1);
Expand Down
190 changes: 132 additions & 58 deletions crates/chat-cli/src/cli/chat/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,40 +19,109 @@ pub mod tool_manager;
pub mod tools;
pub mod util;
use std::borrow::Cow;
use std::collections::{HashMap, VecDeque};
use std::io::{IsTerminal, Read, Write};
use std::collections::{
HashMap,
VecDeque,
};
use std::io::{
IsTerminal,
Read,
Write,
};
use std::process::ExitCode;
use std::sync::Arc;
use std::time::{Duration, Instant};
use std::time::{
Duration,
Instant,
};

use amzn_codewhisperer_client::types::SubscriptionStatus;
use clap::{Args, CommandFactory, Parser};
use clap::{
Args,
CommandFactory,
Parser,
};
use cli::compact::CompactStrategy;
use cli::model::{get_available_models, select_model};
use cli::model::{
get_available_models,
select_model,
};
pub use conversation::ConversationState;
use conversation::TokenWarningLevel;
use crossterm::style::{Attribute, Color, Stylize};
use crossterm::{cursor, execute, queue, style, terminal};
use tool_manager::{PromptQuery, PromptQueryResult};
use eyre::{Report, Result, bail, eyre};
use crossterm::style::{
Attribute,
Color,
Stylize,
};
use crossterm::{
cursor,
execute,
queue,
style,
terminal,
};
use eyre::{
Report,
Result,
bail,
eyre,
};
use input_source::InputSource;
use message::{AssistantMessage, AssistantToolUse, ToolUseResult, ToolUseResultBlock};
use parse::{ParseState, interpret_markdown};
use parser::{RecvErrorKind, RequestMetadata, SendMessageStream};
use message::{
AssistantMessage,
AssistantToolUse,
ToolUseResult,
ToolUseResultBlock,
};
use parse::{
ParseState,
interpret_markdown,
};
use parser::{
RecvErrorKind,
RequestMetadata,
SendMessageStream,
};
use regex::Regex;
use spinners::{Spinner, Spinners};
use spinners::{
Spinner,
Spinners,
};
use thiserror::Error;
use time::OffsetDateTime;
use token_counter::TokenCounter;
use tokio::signal::ctrl_c;
use tokio::sync::{Mutex, broadcast};
use tool_manager::{ToolManager, ToolManagerBuilder};
use tokio::sync::{
Mutex,
broadcast,
};
use tool_manager::{
PromptQuery,
PromptQueryResult,
ToolManager,
ToolManagerBuilder,
};
use tools::gh_issue::GhIssueContext;
use tools::{NATIVE_TOOLS, OutputKind, QueuedTool, Tool, ToolSpec};
use tracing::{debug, error, info, trace, warn};
use tools::{
NATIVE_TOOLS,
OutputKind,
QueuedTool,
Tool,
ToolSpec,
};
use tracing::{
debug,
error,
info,
trace,
warn,
};
use util::images::RichImageBlock;
use util::ui::draw_box;
use util::{animate_output, play_notification_bell};
use util::{
animate_output,
play_notification_bell,
};
use winnow::Partial;
use winnow::stream::Offset;

Expand All @@ -61,22 +130,36 @@ use super::agent::{
PermissionEvalResult,
};
use crate::api_client::model::ToolResultStatus;
use crate::api_client::{self, ApiClientError};
use crate::api_client::{
self,
ApiClientError,
};
use crate::auth::AuthError;
use crate::auth::builder_id::is_idc_user;
use crate::cli::agent::Agents;
use crate::cli::chat::cli::SlashCommand;
use crate::cli::chat::cli::model::find_model;
use crate::cli::chat::cli::prompts::{GetPromptError, PromptsSubcommand};
use crate::cli::chat::cli::prompts::{
GetPromptError,
PromptsSubcommand,
};
use crate::cli::chat::util::sanitize_unicode_tags;
use crate::database::settings::Setting;
use crate::mcp_client::Prompt;
use crate::os::Os;
use crate::telemetry::core::{
AgentConfigInitArgs, ChatAddedMessageParams, ChatConversationType, MessageMetaTag, RecordUserTurnCompletionArgs,
AgentConfigInitArgs,
ChatAddedMessageParams,
ChatConversationType,
MessageMetaTag,
RecordUserTurnCompletionArgs,
ToolUseEventBuilder,
};
use crate::telemetry::{ReasonCode, TelemetryResult, get_error_reason};
use crate::telemetry::{
ReasonCode,
TelemetryResult,
get_error_reason,
};
use crate::util::MCP_SERVER_TOOL_DELIMITER;

const LIMIT_REACHED_TEXT: &str = color_print::cstr! { "You've used all your free requests for this month. You have two options:
Expand Down Expand Up @@ -189,17 +272,13 @@ impl ChatArgs {
agents.trust_all_tools = self.trust_all_tools;

os.telemetry
.send_agent_config_init(
&os.database,
conversation_id.clone(),
AgentConfigInitArgs {
agents_loaded_count: md.load_count as i64,
agents_loaded_failed_count: md.load_failed_count as i64,
legacy_profile_migration_executed: md.migration_performed,
legacy_profile_migrated_count: md.migrated_count as i64,
launched_agent: md.launched_agent,
},
)
.send_agent_config_init(&os.database, conversation_id.clone(), AgentConfigInitArgs {
agents_loaded_count: md.load_count as i64,
agents_loaded_failed_count: md.load_failed_count as i64,
legacy_profile_migration_executed: md.migration_performed,
legacy_profile_migrated_count: md.migrated_count as i64,
launched_agent: md.launched_agent,
})
.await
.map_err(|err| error!(?err, "failed to send agent config init telemetry"))
.ok();
Expand Down Expand Up @@ -2693,31 +2772,26 @@ impl ChatSession {
};

os.telemetry
.send_record_user_turn_completion(
&os.database,
conversation_id,
result,
RecordUserTurnCompletionArgs {
message_ids: mds.iter().map(|md| md.message_id.clone()).collect::<_>(),
request_ids: mds.iter().map(|md| md.request_id.clone()).collect::<_>(),
reason,
reason_desc,
status_code,
time_to_first_chunks_ms: mds
.iter()
.map(|md| md.time_to_first_chunk.map(|d| d.as_secs_f64() * 1000.0))
.collect::<_>(),
chat_conversation_type: md.and_then(|md| md.chat_conversation_type),
assistant_response_length: mds.iter().map(|md| md.response_size as i64).sum(),
message_meta_tags: mds.last().map(|md| md.message_meta_tags.clone()).unwrap_or_default(),
user_prompt_length: mds.first().map(|md| md.user_prompt_length).unwrap_or_default() as i64,
user_turn_duration_seconds,
follow_up_count: mds
.iter()
.filter(|md| matches!(md.chat_conversation_type, Some(ChatConversationType::ToolUse)))
.count() as i64,
},
)
.send_record_user_turn_completion(&os.database, conversation_id, result, RecordUserTurnCompletionArgs {
message_ids: mds.iter().map(|md| md.message_id.clone()).collect::<_>(),
request_ids: mds.iter().map(|md| md.request_id.clone()).collect::<_>(),
reason,
reason_desc,
status_code,
time_to_first_chunks_ms: mds
.iter()
.map(|md| md.time_to_first_chunk.map(|d| d.as_secs_f64() * 1000.0))
.collect::<_>(),
chat_conversation_type: md.and_then(|md| md.chat_conversation_type),
assistant_response_length: mds.iter().map(|md| md.response_size as i64).sum(),
message_meta_tags: mds.last().map(|md| md.message_meta_tags.clone()).unwrap_or_default(),
user_prompt_length: mds.first().map(|md| md.user_prompt_length).unwrap_or_default() as i64,
user_turn_duration_seconds,
follow_up_count: mds
.iter()
.filter(|md| matches!(md.chat_conversation_type, Some(ChatConversationType::ToolUse)))
.count() as i64,
})
.await
.ok();
}
Expand Down
30 changes: 26 additions & 4 deletions crates/chat-cli/src/cli/chat/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,36 @@ use std::borrow::Cow;
use std::cell::RefCell;

use eyre::Result;
use rustyline::completion::{Completer, FilenameCompleter, extract_word};
use rustyline::completion::{
Completer,
FilenameCompleter,
extract_word,
};
use rustyline::error::ReadlineError;
use rustyline::highlight::{CmdKind, Highlighter};
use rustyline::highlight::{
CmdKind,
Highlighter,
};
use rustyline::hint::Hinter as RustylineHinter;
use rustyline::history::DefaultHistory;
use rustyline::validate::{ValidationContext, ValidationResult, Validator};
use rustyline::validate::{
ValidationContext,
ValidationResult,
Validator,
};
use rustyline::{
Cmd, Completer, CompletionType, Config, Context, EditMode, Editor, EventHandler, Helper, Hinter, KeyCode, KeyEvent,
Cmd,
Completer,
CompletionType,
Config,
Context,
EditMode,
Editor,
EventHandler,
Helper,
Hinter,
KeyCode,
KeyEvent,
Modifiers,
};
use winnow::stream::AsChar;
Expand Down
3 changes: 2 additions & 1 deletion crates/chat-cli/src/cli/chat/prompt_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ pub struct PromptComponents {

/// Parse prompt components from a plain text prompt
pub fn parse_prompt_components(prompt: &str) -> Option<PromptComponents> {
// Expected format: "[agent] !> " or "> " or "!> " or "[agent] ↯ > " or "↯ > " or "[agent] ↯ !> " etc.
// Expected format: "[agent] !> " or "> " or "!> " or "[agent] ↯ > " or "↯ > " or "[agent] ↯ !> "
// etc.
let mut profile = None;
let mut warning = false;
let mut tangent_mode = false;
Expand Down
Loading