use anyhow::Result;
use crate::config::Config;
use crate::db::models::Session;
use crate::services::SessionService;
pub async fn create_channel_session(
session_svc: &SessionService,
title: Option<String>,
inherit_wd_from: Option<&Session>,
) -> Result<Session> {
create_channel_session_reported(session_svc, title, inherit_wd_from)
.await
.map(|(session, _)| session)
}
pub async fn create_channel_session_reported(
session_svc: &SessionService,
title: Option<String>,
inherit_wd_from: Option<&Session>,
) -> Result<(Session, bool)> {
let (mut inherited_provider, mut inherited_model) =
match session_svc.get_most_recent_session().await {
Ok(Some(prev)) => (prev.provider_name, prev.model),
_ => (None, None),
};
let config = Config::load().ok();
if let (Some(name), Some(cfg)) = (inherited_provider.as_deref(), config.as_ref())
&& !provider_enabled(cfg, name)
{
tracing::info!(
"Channel session: not inheriting disabled provider {name:?}; using [agent] defaults"
);
inherited_provider = None;
inherited_model = None;
}
if inherited_provider.is_none()
&& let Some(config) = config.as_ref()
&& config.agent.default_provider.is_some()
{
inherited_provider = config.agent.default_provider.clone();
inherited_model = config.agent.default_model.clone();
tracing::info!(
"Channel session using [agent] defaults: provider {:?} / model {:?}",
inherited_provider,
inherited_model,
);
}
let inherited_wd = inherit_wd_from.and_then(|s| s.working_directory.clone());
if inherited_provider.is_some() || inherited_wd.is_some() {
tracing::info!(
"Channel session inherited provider {:?} / model {:?} / wd {:?}",
inherited_provider,
inherited_model,
inherited_wd,
);
}
create_with_chat_identity_reported(
session_svc,
title,
inherited_provider,
inherited_model,
inherited_wd,
)
.await
}
pub(crate) async fn create_with_chat_identity_reported(
session_svc: &SessionService,
title: Option<String>,
provider: Option<String>,
model: Option<String>,
wd: Option<String>,
) -> Result<(Session, bool)> {
let chat_key = title.as_deref().and_then(|t| {
let idx = t.rfind("[chat:")?;
Some(t[idx..].to_string())
});
match chat_key {
Some(key) => {
session_svc
.insert_or_resolve_channel_session_reported(title, provider, model, wd, &key)
.await
}
None => {
let session = session_svc
.create_session_with_provider(title, provider, model, wd)
.await?;
Ok((session, true))
}
}
}
fn provider_enabled(config: &Config, name: &str) -> bool {
crate::brain::provider::factory::provider_config_by_name(config, name)
.is_some_and(|p| p.enabled)
}
pub async fn start_new_channel_session(
session_svc: &SessionService,
chat_key: &str,
legacy_title: &str,
keep_prior_live: bool,
log_prefix: &str,
) -> Result<Session> {
let prior_session = match session_svc.find_session_by_channel_chat_key(chat_key).await {
Ok(found) => found,
Err(e) => {
tracing::error!("{log_prefix}: /new prior-session lookup failed: {e:#}");
None
}
};
let prior_session = match prior_session {
Some(s) => Some(s),
None => session_svc
.find_session_by_title_suffix(chat_key)
.await
.unwrap_or_else(|e| {
tracing::error!("{log_prefix}: /new title-suffix lookup failed: {e:#}");
None
}),
};
if let Some(old) = prior_session.as_ref() {
let handed_over = if keep_prior_live {
session_svc.release_channel_chat_key(old.id).await
} else {
session_svc.archive_session(old.id).await
};
if let Err(e) = handed_over {
tracing::error!(
"{log_prefix}: /new could not hand the chat key over from {}: {e:#}",
old.id
);
}
}
let current_title = format!("{legacy_title} {chat_key}");
create_channel_session(session_svc, Some(current_title), prior_session.as_ref()).await
}