use super::*;
use crate::persona_route::persona_backend_route;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct PreferenceBaseline {
pub provider: Option<String>,
pub model: Option<String>,
pub cognition: newt_core::cognition::CognitionOverride,
pub tenacity: Option<newt_core::Tenacity>,
pub initiative: Option<newt_core::Initiative>,
}
impl PreferenceBaseline {
pub(crate) fn snapshot(provider: Option<String>, model: Option<String>) -> Self {
Self {
provider,
model,
cognition: newt_core::cognition::cli_cognition(),
tenacity: newt_core::tenacity::cli_tenacity(),
initiative: newt_core::initiative::cli_initiative(),
}
}
}
pub(crate) struct ConversationPreferenceSwitch<'a> {
pub store: Option<&'a newt_core::ConversationStore>,
pub conversation_id: &'a str,
pub baseline: &'a PreferenceBaseline,
pub persona: Option<&'a Persona>,
pub pending: &'a mut newt_core::PreferenceActions,
pub base_provider: &'a mut Option<String>,
pub base_model: &'a mut Option<String>,
pub cfg: &'a newt_core::ResolvedConfig,
pub choice: &'a mut BackendChoice,
pub inf_url: &'a mut String,
pub inf_model: &'a mut String,
pub inf_kind: &'a mut newt_core::BackendKind,
pub inf_key: &'a mut Option<String>,
pub inf_context_window: &'a mut Option<u32>,
pub color: bool,
pub verbose: bool,
}
pub(crate) struct PinRestore {
pub url_changed: bool,
pub degraded: Option<PinDegraded>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct PinDegraded {
pub reasons: Vec<String>,
pub pin: newt_core::OperatorPreferencePin,
}
impl PinDegraded {
pub fn summary(&self) -> String {
format!("!pin — {}", self.reasons.join("; "))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum StartupConversation {
Fresh,
ResumedHeld,
ResumedRefused,
}
impl StartupConversation {
pub(crate) fn applies_pin(self) -> bool {
matches!(self, Self::ResumedHeld)
}
}
pub(crate) fn apply_startup_preference_pin(
outcome: StartupConversation,
sw: ConversationPreferenceSwitch<'_>,
) -> bool {
if !outcome.applies_pin() {
return false;
}
restore_preference_pin(sw).url_changed
}
pub(crate) fn restore_preference_pin(sw: ConversationPreferenceSwitch<'_>) -> PinRestore {
let ConversationPreferenceSwitch {
store,
conversation_id,
baseline,
persona,
pending,
base_provider,
base_model,
cfg,
choice,
inf_url,
inf_model,
inf_kind,
inf_key,
inf_context_window,
color,
verbose,
} = sw;
*pending = newt_core::PreferenceActions::default();
let mut pin_read_failed = false;
let pin = match store.map(|s| s.preference_pin(conversation_id)) {
Some(Ok(Some(pin))) => pin,
None | Some(Ok(None)) => newt_core::OperatorPreferencePin::default(),
Some(Err(e)) => {
print_newt(
&format!(
"warning: could not read the conversation preference pin ({e}) — \
using this run's baseline preferences"
),
color,
verbose,
);
pin_read_failed = true;
newt_core::OperatorPreferencePin::default()
}
};
let owned = newt_core::runtime::cli_preference_axes();
let configured: Vec<&str> = cfg.backends.iter().map(|b| b.name.as_str()).collect();
let plan = pin.apply_plan(&configured, owned);
for notice in &plan.notices {
print_newt(notice, color, verbose);
}
let mut degraded = (!plan.notices.is_empty() || pin_read_failed).then(|| PinDegraded {
reasons: plan.notices.clone(),
pin: pin.clone(),
});
if let Some(d) = degraded.as_mut() {
if d.reasons.is_empty() {
d.reasons
.push("the stored preference pin could not be read".to_string());
}
}
newt_core::cognition::set_cli_cognition(baseline.cognition);
match baseline.tenacity {
Some(t) => newt_core::tenacity::set_cli_tenacity(t),
None => newt_core::tenacity::clear_cli_tenacity(),
}
match baseline.initiative {
Some(i) => newt_core::initiative::set_cli_initiative(i),
None => newt_core::initiative::clear_cli_initiative(),
}
*base_provider = baseline.provider.clone();
*base_model = baseline.model.clone();
let mut applied: Vec<String> = Vec::new();
if let Some(o) = plan.cognition {
newt_core::cognition::set_cli_cognition(o);
applied.push(format!(
"cognition {}",
pin.cognition.as_deref().unwrap_or("?")
));
}
if let Some(t) = plan.tenacity {
newt_core::tenacity::set_cli_tenacity(t);
applied.push(format!("tenacity {}", t.label()));
}
if let Some(i) = plan.initiative {
newt_core::initiative::set_cli_initiative(i);
applied.push(format!("initiative {}", i.label()));
}
let (mut provider, mut model) =
match persona_backend_route(persona.map(|p| &p.profile), &configured) {
Ok(Some((backend, model))) => (Some(backend), model),
Ok(None) | Err(_) => (baseline.provider.clone(), baseline.model.clone()),
};
match plan.backend_axis {
newt_core::BackendAxisAction::Leave => {}
newt_core::BackendAxisAction::Route {
provider: pinned,
model: pinned_model,
} => {
applied.push(match &pinned_model {
newt_core::RouteModel::Set(m) => format!("backend {pinned} (model {m})"),
newt_core::RouteModel::Clear => format!("backend {pinned}"),
newt_core::RouteModel::Keep => {
format!("backend {pinned} (this run's model kept)")
}
});
provider = Some(pinned);
match pinned_model {
newt_core::RouteModel::Set(m) => model = Some(m),
newt_core::RouteModel::Clear => model = None,
newt_core::RouteModel::Keep => {}
}
}
newt_core::BackendAxisAction::ModelOnly(pinned_model) => {
applied.push(format!("model {pinned_model}"));
model = Some(pinned_model);
}
}
let mut url_changed = false;
let live = (
std::env::var("NEWT_PROVIDER").ok(),
std::env::var("NEWT_DGX_MODEL").ok(),
);
if live != (provider.clone(), model.clone()) {
{
let _env = newt_core::process_env::lock();
newt_core::process_env::set_or_remove("NEWT_PROVIDER", provider.as_deref());
newt_core::process_env::set_or_remove("NEWT_DGX_MODEL", model.as_deref());
}
url_changed = refresh_backend(
cfg,
choice,
inf_url,
inf_model,
inf_kind,
inf_key,
inf_context_window,
color,
verbose,
);
}
if !applied.is_empty() {
print_newt(
&format!("session preferences restored: {}", applied.join(" · ")),
color,
verbose,
);
}
let suppressed = newt_core::PreferenceAxes {
backend: owned.backend && pin.backend.is_some(),
model: owned.model && pin.model.is_some(),
cognition: owned.cognition && pin.cognition.is_some(),
tenacity: owned.tenacity && pin.tenacity.is_some(),
initiative: owned.initiative && pin.initiative.is_some(),
};
if !suppressed.is_empty() {
print_newt(
&format!(
"session preferences: this run's explicit {} beats the pin (kept for the next run)",
suppressed.labels().join(" · ")
),
color,
verbose,
);
}
PinRestore {
url_changed,
degraded,
}
}