Files
zesdex/apps/interfaces/tui/src/turn.rs
T

106 lines
3.4 KiB
Rust
Raw Normal View History

//! TUI agent turn interface adapter — delegates execution to `zesdex_infrastructure::agent`.
use std::sync::atomic::Ordering;
use tracing::info;
use zesdex_domain::core::ChatMessage;
use zesdex_domain::agent::AgentTurnParams;
use crate::state::AppStateRest;
/// Spawn an agent turn on a background thread by delegating to `zesdex-infrastructure`.
#[tracing::instrument(skip(state))]
pub fn spawn_agent_turn(state: &mut AppStateRest, text: String) {
// compare_exchange: only mark in-flight if not already running
if state
.turn_in_flight_flag
.compare_exchange(false, true, Ordering::SeqCst, Ordering::Relaxed)
.is_err()
{
return; // already running
}
let turn_events = state.turn_events.clone();
let in_flight = state.turn_in_flight_flag.clone();
let abort = state.abort_flag.clone();
let session_dir = state.session_dir.clone();
let workspace_roots = state.workspace_roots.clone();
// Resolve LLM provider configuration from settings
let provider_name = &state.settings.provider;
let provider_cfg = state.app_config.providers.get(provider_name).cloned();
let mut api_key = String::new();
if let Some(key) = state.settings.api_keys.get(provider_name) {
api_key = key.clone();
} else if let Some(ref cfg) = provider_cfg {
if let Some(ref default_key) = cfg.default_api_key {
api_key = default_key.clone();
}
if api_key.is_empty() {
if let Some(ref env_name) = cfg.api_key_env {
if let Ok(val) = std::env::var(env_name) {
api_key = val;
}
}
}
}
let model = state.settings.model.clone();
let api_base = provider_cfg.map(|cfg| cfg.api_base.clone());
let mut messages: Vec<ChatMessage> = state
.session_runtime
.as_ref()
.map(|rt| rt.messages.clone())
.unwrap_or_default();
messages.push(ChatMessage::user(text));
if let Some(ref mut rt) = state.session_runtime {
rt.messages = messages.clone();
}
info!("delegating agent turn to infrastructure engine (model: {})", model);
let params = AgentTurnParams {
messages,
session_dir: session_dir.clone(),
workspace_roots: workspace_roots.clone(),
turn_events: turn_events.clone(),
in_flight: in_flight.clone(),
abort: abort.clone(),
api_key: api_key.clone(),
model: model.clone(),
api_base: api_base.clone(),
};
let client = std::sync::Arc::new(zesdex_infrastructure::llm::provider::LlmClient::new(
api_key,
model,
api_base,
));
let tool_ctx = zesdex_infrastructure::tools::ToolCtx::builder()
.session_dir(session_dir)
.workspaces(workspace_roots)
.turn_events(turn_events)
.build();
let tool_executor = std::sync::Arc::new(
zesdex_infrastructure::tools::executor::InfrastructureToolExecutor::new(tool_ctx),
);
let tools = zesdex_infrastructure::tools::all_tools();
let defs = zesdex_infrastructure::tools::tool_defs(&tools);
let turn_service = zesdex_application::agent::turn_service::AgentTurnServiceImpl::new(
client,
tool_executor,
defs,
);
use zesdex_application::agent::AgentTurnService;
tokio::spawn(async move {
let _ = turn_service.run_turn(params).await;
});
}