use pretty_assertions::assert_eq;
use super::super::{
agent_picker::{InternalAgentModelPickerOrigin, InternalAgentModelTarget},
tests::test_app,
ComposerMode,
};
use crate::{agent::PERMISSION_CLASSIFIER_AGENT_ID, permission::PermissionMode};
fn startup_target() -> InternalAgentModelTarget {
InternalAgentModelTarget {
id: PERMISSION_CLASSIFIER_AGENT_ID.into(),
origin: InternalAgentModelPickerOrigin::PermissionModeStartup,
}
}
fn config_row_target() -> InternalAgentModelTarget {
InternalAgentModelTarget {
id: PERMISSION_CLASSIFIER_AGENT_ID.into(),
origin: InternalAgentModelPickerOrigin::PermissionModeConfigRow,
}
}
#[test]
fn cancel_startup_classifier_prompt_marks_pending_demote() {
let mut app = test_app();
app.info.runtime.permission_mode = PermissionMode::Auto;
app.internal_agent_model_target = Some(startup_target());
assert!(app.cancel_permission_classifier_model_prompt( true));
assert!(app.pending_auto_classifier_demote);
assert!(app.internal_agent_model_target.is_none());
assert!(matches!(app.input_ui.composer(), ComposerMode::Input));
assert_eq!(
app.status(),
"permission mode set to supervised: no classifier model selected"
);
}
#[test]
fn cancel_config_row_classifier_prompt_keeps_mode_without_demote() {
let mut app = test_app();
app.info.runtime.permission_mode = PermissionMode::Supervised;
app.internal_agent_model_target = Some(config_row_target());
assert!(app.cancel_permission_classifier_model_prompt( true));
assert!(!app.pending_auto_classifier_demote);
assert_eq!(app.info.runtime.permission_mode, PermissionMode::Supervised);
assert_eq!(
app.status(),
"permission mode stays supervised: no classifier model selected"
);
}
#[tokio::test]
async fn finish_startup_without_selection_does_not_mark_demote() {
use crate::app::interactive_runtime::test_edit_tool_runtime;
use crate::config::EditTool;
let mut app = test_app();
app.info.runtime.permission_mode = PermissionMode::Auto;
app.pending_auto_classifier_demote = false;
let mut agent = test_edit_tool_runtime(EditTool::Auto).await;
app.finish_permission_classifier_model_selection(
false,
InternalAgentModelPickerOrigin::PermissionModeStartup,
&mut agent,
)
.await
.unwrap();
assert!(!app.pending_auto_classifier_demote);
assert_eq!(app.info.runtime.permission_mode, PermissionMode::Auto);
}
#[tokio::test]
async fn reconcile_auto_without_classifier_opens_picker_or_demotes() {
use crate::app::interactive_runtime::test_edit_tool_runtime;
use crate::config::EditTool;
let mut app = test_app();
app.info.runtime.permission_mode = PermissionMode::Auto;
app.info.runtime.internal_agents.clear();
let mut agent = test_edit_tool_runtime(EditTool::Auto).await;
agent
.set_permission_mode(PermissionMode::Auto)
.await
.unwrap();
app.reconcile_auto_classifier_gate(&mut agent)
.await
.unwrap();
let opened_startup_picker = matches!(
app.internal_agent_model_target.as_ref().map(|t| t.origin),
Some(InternalAgentModelPickerOrigin::PermissionModeStartup)
) && matches!(app.input_ui.composer(), ComposerMode::Picker(_));
let demoted = app.info.runtime.permission_mode == PermissionMode::Supervised
&& agent.permission_mode() == PermissionMode::Supervised;
assert!(
opened_startup_picker || demoted,
"expected startup picker or Supervised fallback, got mode={:?}",
app.info.runtime.permission_mode,
);
}
#[tokio::test]
async fn reconcile_applies_pending_startup_demote() {
use crate::app::interactive_runtime::test_edit_tool_runtime;
use crate::config::EditTool;
let mut app = test_app();
app.info.runtime.permission_mode = PermissionMode::Auto;
app.info.runtime.internal_agents.clear();
app.pending_auto_classifier_demote = true;
let mut agent = test_edit_tool_runtime(EditTool::Auto).await;
agent
.set_permission_mode(PermissionMode::Auto)
.await
.unwrap();
app.reconcile_auto_classifier_gate(&mut agent)
.await
.unwrap();
assert!(!app.pending_auto_classifier_demote);
assert_eq!(app.info.runtime.permission_mode, PermissionMode::Supervised);
assert_eq!(agent.permission_mode(), PermissionMode::Supervised);
}