Skip to content

Commit e58ea07

Browse files
committed
add modelId in telemetry & persist modelId
1 parent 06dc7c9 commit e58ea07

File tree

7 files changed

+100
-27
lines changed

7 files changed

+100
-27
lines changed

crates/chat-cli/src/cli/chat/conversation_state.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ pub struct ConversationState {
105105
latest_summary: Option<String>,
106106
#[serde(skip)]
107107
pub updates: Option<SharedWriter>,
108-
/// Model explicitly selected by the user in this conversation state via `/model`. (`None` == auto)
108+
/// Model explicitly selected by the user in this conversation state via `/model`. (`None` ==
109+
/// auto)
109110
#[serde(skip)]
110111
pub current_model_id: Option<String>,
111112
}

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

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,10 @@ impl ChatContext {
567567
let output_clone = output.clone();
568568

569569
let mut existing_conversation = false;
570-
let model_id = database.settings.get_string(Setting::UserDefaultModel);
570+
let model_id = match database.get_last_used_model_id() {
571+
Ok(Some(id)) => Some(id),
572+
Ok(None) | Err(_) => database.settings.get_string(Setting::UserDefaultModel),
573+
};
571574
let conversation_state = if resume_conversation {
572575
let prior = std::env::current_dir()
573576
.ok()
@@ -594,7 +597,7 @@ impl ChatContext {
594597
profile,
595598
Some(output_clone),
596599
tool_manager,
597-
model_id
600+
model_id,
598601
)
599602
.await
600603
}
@@ -606,7 +609,7 @@ impl ChatContext {
606609
profile,
607610
Some(output_clone),
608611
tool_manager,
609-
model_id
612+
model_id,
610613
)
611614
.await
612615
};
@@ -3042,32 +3045,67 @@ impl ChatContext {
30423045
},
30433046
Command::Model => {
30443047
queue!(self.output, style::Print("\n"))?;
3045-
let labels: Vec<&str> = MODEL_OPTIONS.iter().map(|(l, _)| *l).collect();
3048+
let active_model_id = self.conversation_state.current_model_id.as_deref();
3049+
let labels: Vec<String> = MODEL_OPTIONS
3050+
.iter()
3051+
.map(|(label, model_id)| {
3052+
if (model_id.is_empty() && active_model_id.is_none()) || Some(*model_id) == active_model_id {
3053+
format!("{} (active)", label)
3054+
} else {
3055+
label.to_string()
3056+
}
3057+
})
3058+
.collect();
3059+
let default_index = MODEL_OPTIONS
3060+
.iter()
3061+
.position(|(_, model_id)| Some(*model_id) == active_model_id)
3062+
.unwrap_or(0);
30463063
let selection: Option<_> = match Select::with_theme(&crate::util::dialoguer_theme())
30473064
.with_prompt("Select a model for this chat session")
30483065
.items(&labels)
3049-
.default(0)
3066+
.default(default_index)
30503067
.interact_on_opt(&dialoguer::console::Term::stdout())
30513068
{
3052-
Ok(sel) => sel,
3069+
Ok(sel) => {
3070+
let _ = crossterm::execute!(
3071+
std::io::stdout(),
3072+
crossterm::style::SetForegroundColor(crossterm::style::Color::Magenta)
3073+
);
3074+
sel
3075+
},
30533076
// Ctrl‑C -> Err(Interrupted)
30543077
Err(DError::IO(ref e)) if e.kind() == io::ErrorKind::Interrupted => None,
30553078
Err(e) => return Err(ChatError::Custom(format!("Failed to choose model: {e}").into())),
30563079
};
30573080

3081+
queue!(self.output, style::ResetColor)?;
3082+
30583083
if let Some(index) = selection {
3059-
let (label, model_opt) = MODEL_OPTIONS[index];
3084+
let (label, model_id) = MODEL_OPTIONS[index];
3085+
let model_id_str = model_id.to_string();
30603086

3061-
self.conversation_state.current_model_id = Some(model_opt.to_string());
3062-
telemetry.update_model_id(self.conversation_state.current_model_id.clone());
3087+
if model_id == "" {
3088+
self.conversation_state.current_model_id = None;
3089+
telemetry.update_model_id(None);
3090+
let _ = database.unset_last_used_model_id();
3091+
} else {
3092+
self.conversation_state.current_model_id = Some(model_id_str.clone());
3093+
telemetry.update_model_id(Some(model_id_str.clone()));
3094+
let _ = database.set_last_used_model_id(model_id_str);
3095+
}
30633096

3064-
use crossterm::{
3065-
queue,
3066-
style,
3067-
};
3068-
queue!(self.output, style::Print("\n"), style::Print(format!(" Swtiched model to {}\n\n", label)))?;
3097+
queue!(
3098+
self.output,
3099+
style::Print("\n"),
3100+
style::Print(format!(" Switched model to {}\n\n", label)),
3101+
style::ResetColor,
3102+
style::SetForegroundColor(Color::Reset),
3103+
style::SetBackgroundColor(Color::Reset),
3104+
)?;
30693105
}
3070-
3106+
3107+
queue!(self.output, style::ResetColor)?;
3108+
self.output.flush()?;
30713109
ChatState::PromptUser {
30723110
tool_uses: None,
30733111
pending_tool_index: None,

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ const IDC_REGION_KEY: &str = "auth.idc.region";
6060
// We include this key to remove for backwards compatibility
6161
const CUSTOMIZATION_STATE_KEY: &str = "api.selectedCustomization";
6262
const ROTATING_TIP_KEY: &str = "chat.greeting.rotating_tips_current_index";
63+
const LAST_USED_MODEL_ID: &str = "lastUsedModelId";
6364

6465
const MIGRATIONS: &[Migration] = migrations![
6566
"000_migration_table",
@@ -307,6 +308,21 @@ impl Database {
307308
Ok(tip)
308309
}
309310

311+
/// Get the model id used for last conversation state.
312+
pub fn get_last_used_model_id(&self) -> Result<Option<String>, DatabaseError> {
313+
self.get_json_entry::<String>(Table::State, LAST_USED_MODEL_ID)
314+
}
315+
316+
/// Set the model id used for last conversation state.
317+
pub fn set_last_used_model_id(&mut self, last_used_model_id: String) -> Result<usize, DatabaseError> {
318+
self.set_json_entry(Table::State, LAST_USED_MODEL_ID, last_used_model_id)
319+
}
320+
321+
/// UnsSet the model id used for last conversation state.
322+
pub fn unset_last_used_model_id(&mut self) -> Result<(), DatabaseError> {
323+
self.delete_entry(Table::State, LAST_USED_MODEL_ID)
324+
}
325+
310326
/// Get a chat conversation given a path to the conversation.
311327
pub fn get_conversation_by_path(
312328
&mut self,

crates/chat-cli/src/database/settings.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,14 +202,12 @@ mod test {
202202
assert_eq!(settings.get(Setting::McpLoadedBefore), None);
203203
assert_eq!(settings.get(Setting::UserDefaultModel), None);
204204

205-
206205
settings.set(Setting::TelemetryEnabled, true).await.unwrap();
207206
settings.set(Setting::OldClientId, "test").await.unwrap();
208207
settings.set(Setting::ShareCodeWhispererContent, false).await.unwrap();
209208
settings.set(Setting::McpLoadedBefore, true).await.unwrap();
210209
settings.set(Setting::UserDefaultModel, "model 1").await.unwrap();
211210

212-
213211
assert_eq!(settings.get(Setting::TelemetryEnabled), Some(&Value::Bool(true)));
214212
assert_eq!(
215213
settings.get(Setting::OldClientId),

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

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ mod install_method;
66

77
use core::ToolUseEventBuilder;
88
use std::str::FromStr;
9-
use std::sync::{Arc, RwLock};
9+
use std::sync::{
10+
Arc,
11+
RwLock,
12+
};
1013

1114
use amzn_codewhisperer_client::types::{
1215
ChatAddMessageEvent,
@@ -148,8 +151,11 @@ impl Clone for TelemetryThread {
148151

149152
impl TelemetryThread {
150153
pub async fn new(env: &Env, database: &mut Database) -> Result<Self, TelemetryError> {
151-
//todo yifan change to last used modelid
152-
let current_model_id = Arc::new(RwLock::new(None));
154+
let model_id = match database.get_last_used_model_id() {
155+
Ok(Some(id)) => Some(id),
156+
Ok(None) | Err(_) => database.settings.get_string(Setting::UserDefaultModel),
157+
};
158+
let current_model_id = Arc::new(RwLock::new(model_id));
153159
let telemetry_client = TelemetryClient::new(env, database, current_model_id.clone()).await?;
154160
let (tx, mut rx) = mpsc::unbounded_channel();
155161
let handle = tokio::spawn(async move {
@@ -330,7 +336,11 @@ struct TelemetryClient {
330336
}
331337

332338
impl TelemetryClient {
333-
async fn new(env: &Env, database: &mut Database, current_model_id: Arc<RwLock<Option<String>>>) -> Result<Self, TelemetryError> {
339+
async fn new(
340+
env: &Env,
341+
database: &mut Database,
342+
current_model_id: Arc<RwLock<Option<String>>>,
343+
) -> Result<Self, TelemetryError> {
334344
let telemetry_enabled = !cfg!(test)
335345
&& env.get_os("Q_DISABLE_TELEMETRY").is_none()
336346
&& database.settings.get_bool(Setting::TelemetryEnabled).unwrap_or(true);
@@ -506,7 +516,13 @@ mod test {
506516
#[tokio::test]
507517
async fn client_context() {
508518
let mut database = Database::new().await.unwrap();
509-
let client = TelemetryClient::new(&Env::new(), &mut database, Arc::new(RwLock::new(Some("model".to_owned())))).await.unwrap();
519+
let client = TelemetryClient::new(
520+
&Env::new(),
521+
&mut database,
522+
Arc::new(RwLock::new(Some("model".to_owned()))),
523+
)
524+
.await
525+
.unwrap();
510526
let context = client.user_context().unwrap();
511527

512528
assert_eq!(context.ide_category, IdeCategory::Cli);
@@ -575,7 +591,13 @@ mod test {
575591
#[ignore = "needs auth which is not in CI"]
576592
async fn test_without_optout() {
577593
let mut database = Database::new().await.unwrap();
578-
let client = TelemetryClient::new(&Env::new(), &mut database, Arc::new(RwLock::new(Some("model".to_owned())))).await.unwrap();
594+
let client = TelemetryClient::new(
595+
&Env::new(),
596+
&mut database,
597+
Arc::new(RwLock::new(Some("model".to_owned()))),
598+
)
599+
.await
600+
.unwrap();
579601
client
580602
.codewhisperer_client
581603
.send_telemetry_event(

crates/fig_api_client/src/clients/client.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use amzn_codewhisperer_client::types::{
1212
TelemetryEvent,
1313
UserContext,
1414
};
15-
use crate::model::ConversationState;
1615
use amzn_consolas_client::Client as ConsolasClient;
1716
use amzn_consolas_client::error::DisplayErrorContext;
1817
use amzn_consolas_client::operation::generate_recommendations::GenerateRecommendationsError;
@@ -224,7 +223,6 @@ impl Client {
224223
Ok(customizations)
225224
}
226225

227-
//(todo) yifan : how to propgate modelID
228226
// .telemetry_event(TelemetryEvent::UserTriggerDecisionEvent(user_trigger_decision_event))
229227
// .user_context(user_context)
230228
// .opt_out_preference(opt_out_preference)

crates/fig_api_client/src/model.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ pub struct UserInputMessage {
646646
pub user_input_message_context: Option<UserInputMessageContext>,
647647
pub user_intent: Option<UserIntent>,
648648
pub images: Option<Vec<ImageBlock>>,
649-
pub model_id: Option<String>
649+
pub model_id: Option<String>,
650650
}
651651

652652
impl From<UserInputMessage> for amzn_codewhisperer_streaming_client::types::UserInputMessage {

0 commit comments

Comments
 (0)