fix(tui): refresh prompt on model switch
This commit is contained in:
@@ -789,10 +789,12 @@ impl Engine {
|
||||
.send(Event::status(format!("Mode changed to: {mode:?}")))
|
||||
.await;
|
||||
}
|
||||
Op::SetModel { model } => {
|
||||
Op::SetModel { model, mode } => {
|
||||
self.session.auto_model = model.trim().eq_ignore_ascii_case("auto");
|
||||
self.session.model = model;
|
||||
self.config.model.clone_from(&self.session.model);
|
||||
self.refresh_system_prompt(mode);
|
||||
self.emit_session_updated().await;
|
||||
let _ = self
|
||||
.tx_event
|
||||
.send(Event::status(format!(
|
||||
|
||||
@@ -1238,6 +1238,61 @@ async fn session_update_preserves_reasoning_tool_only_turn() {
|
||||
assert_eq!(messages, vec![assistant]);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn set_model_reloads_instruction_sources_and_updates_session_prompt() {
|
||||
let tmp = tempdir().expect("tempdir");
|
||||
let instructions = tmp.path().join("instructions.md");
|
||||
fs::write(&instructions, "FLASH_INSTRUCTIONS_MARKER").expect("write instructions");
|
||||
let config = EngineConfig {
|
||||
workspace: tmp.path().to_path_buf(),
|
||||
model: "deepseek-v4-flash".to_string(),
|
||||
instructions: vec![instructions.clone().into()],
|
||||
..Default::default()
|
||||
};
|
||||
let (engine, handle) = Engine::new(config, &Config::default());
|
||||
fs::write(&instructions, "PRO_INSTRUCTIONS_MARKER").expect("rewrite instructions");
|
||||
|
||||
let run = tokio::spawn(engine.run());
|
||||
handle
|
||||
.send(Op::SetModel {
|
||||
model: "deepseek-v4-pro".to_string(),
|
||||
mode: AppMode::Agent,
|
||||
})
|
||||
.await
|
||||
.expect("send set model");
|
||||
|
||||
let (model, prompt) = {
|
||||
let mut rx = handle.rx_event.write().await;
|
||||
loop {
|
||||
let event = tokio::time::timeout(std::time::Duration::from_secs(1), rx.recv())
|
||||
.await
|
||||
.expect("session update after model switch")
|
||||
.expect("event");
|
||||
if let Event::SessionUpdated {
|
||||
model,
|
||||
system_prompt,
|
||||
..
|
||||
} = event
|
||||
{
|
||||
let prompt = match system_prompt.expect("system prompt") {
|
||||
SystemPrompt::Text(text) => text,
|
||||
SystemPrompt::Blocks(blocks) => blocks
|
||||
.into_iter()
|
||||
.map(|block| block.text)
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n"),
|
||||
};
|
||||
break (model, prompt);
|
||||
}
|
||||
}
|
||||
};
|
||||
run.abort();
|
||||
|
||||
assert_eq!(model, "deepseek-v4-pro");
|
||||
assert!(prompt.contains("PRO_INSTRUCTIONS_MARKER"));
|
||||
assert!(!prompt.contains("FLASH_INSTRUCTIONS_MARKER"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detects_context_length_errors_from_provider_payloads() {
|
||||
let msg = r#"SSE stream request failed: HTTP 400 Bad Request: {"error":{"message":"This model's maximum context length is 131072 tokens. However, you requested 153056 tokens (148960 in the messages, 4096 in the completion).","type":"invalid_request_error"}}"#;
|
||||
|
||||
@@ -63,9 +63,9 @@ pub enum Op {
|
||||
#[allow(dead_code)]
|
||||
ChangeMode { mode: AppMode },
|
||||
|
||||
/// Update the model being used
|
||||
/// Update the model being used and refresh the prompt for the current mode.
|
||||
#[allow(dead_code)]
|
||||
SetModel { model: String },
|
||||
SetModel { model: String, mode: AppMode },
|
||||
|
||||
/// Update auto-compaction settings
|
||||
SetCompaction { config: CompactionConfig },
|
||||
|
||||
@@ -3437,6 +3437,7 @@ async fn run_event_loop(
|
||||
let _ = engine_handle
|
||||
.send(Op::SetModel {
|
||||
model: app.model.clone(),
|
||||
mode: app.mode,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@@ -4748,10 +4749,12 @@ async fn dispatch_user_message(
|
||||
async fn apply_model_and_compaction_update(
|
||||
engine_handle: &EngineHandle,
|
||||
compaction: crate::compaction::CompactionConfig,
|
||||
mode: AppMode,
|
||||
) {
|
||||
let _ = engine_handle
|
||||
.send(Op::SetModel {
|
||||
model: compaction.model.clone(),
|
||||
mode,
|
||||
})
|
||||
.await;
|
||||
let _ = engine_handle
|
||||
@@ -4779,6 +4782,7 @@ async fn drain_web_config_events(
|
||||
apply_model_and_compaction_update(
|
||||
engine_handle,
|
||||
app.compaction_config(),
|
||||
app.mode,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
@@ -4803,6 +4807,7 @@ async fn drain_web_config_events(
|
||||
apply_model_and_compaction_update(
|
||||
engine_handle,
|
||||
app.compaction_config(),
|
||||
app.mode,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
@@ -4888,7 +4893,7 @@ async fn apply_model_picker_choice(
|
||||
}
|
||||
|
||||
if model_changed {
|
||||
apply_model_and_compaction_update(engine_handle, app.compaction_config()).await;
|
||||
apply_model_and_compaction_update(engine_handle, app.compaction_config(), app.mode).await;
|
||||
}
|
||||
|
||||
let model_summary = if model_is_auto {
|
||||
@@ -5237,7 +5242,7 @@ async fn apply_command_result(
|
||||
}
|
||||
}
|
||||
AppAction::UpdateCompaction(compaction) => {
|
||||
apply_model_and_compaction_update(engine_handle, compaction).await;
|
||||
apply_model_and_compaction_update(engine_handle, compaction, app.mode).await;
|
||||
}
|
||||
AppAction::OpenConfigEditor(mode) => match mode {
|
||||
ConfigUiMode::Native => {
|
||||
@@ -5267,6 +5272,7 @@ async fn apply_command_result(
|
||||
apply_model_and_compaction_update(
|
||||
engine_handle,
|
||||
app.compaction_config(),
|
||||
app.mode,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
@@ -6743,7 +6749,8 @@ async fn handle_view_events(
|
||||
if let Some(action) = result.action {
|
||||
match action {
|
||||
AppAction::UpdateCompaction(compaction) => {
|
||||
apply_model_and_compaction_update(engine_handle, compaction).await;
|
||||
apply_model_and_compaction_update(engine_handle, compaction, app.mode)
|
||||
.await;
|
||||
}
|
||||
AppAction::OpenConfigView => {}
|
||||
_ => {}
|
||||
|
||||
@@ -2021,11 +2021,12 @@ async fn model_change_update_syncs_engine_model_before_compaction() {
|
||||
let compaction = app.compaction_config();
|
||||
let mut engine = crate::core::engine::mock_engine_handle();
|
||||
|
||||
apply_model_and_compaction_update(&engine.handle, compaction).await;
|
||||
apply_model_and_compaction_update(&engine.handle, compaction, app.mode).await;
|
||||
|
||||
match engine.rx_op.recv().await.expect("set model op") {
|
||||
crate::core::ops::Op::SetModel { model } => {
|
||||
crate::core::ops::Op::SetModel { model, mode } => {
|
||||
assert_eq!(model, "deepseek-v4-flash");
|
||||
assert_eq!(mode, app.mode);
|
||||
}
|
||||
other => panic!("expected SetModel, got {other:?}"),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user