feat: 99% complete migration to new state structs to get away from God-Config struct; i.e. AppConfig, AppState, and RequestContext

This commit is contained in:
2026-04-19 17:05:27 -06:00
parent c6c10b5e24
commit d81508c22a
90 changed files with 18983 additions and 3448 deletions
+20 -21
View File
@@ -1,7 +1,8 @@
use super::*;
use crate::config::paths;
use crate::{
config::{Config, GlobalConfig, Input},
config::{AppConfig, Input, RequestContext},
function::{FunctionDeclaration, ToolCall, ToolResult, eval_tool_calls},
render::render_stream,
utils::*,
@@ -24,7 +25,7 @@ use tokio::sync::mpsc::unbounded_channel;
pub const MODELS_YAML: &str = include_str!("../../models.yaml");
pub static ALL_PROVIDER_MODELS: LazyLock<Vec<ProviderModels>> = LazyLock::new(|| {
Config::local_models_override()
paths::local_models_override()
.ok()
.unwrap_or_else(|| serde_yaml::from_str(MODELS_YAML).unwrap())
});
@@ -37,7 +38,7 @@ static ESCAPE_SLASH_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"(?<!\\)/
#[async_trait::async_trait]
pub trait Client: Sync + Send {
fn global_config(&self) -> &GlobalConfig;
fn app_config(&self) -> &AppConfig;
fn extra_config(&self) -> Option<&ExtraConfig>;
@@ -58,7 +59,7 @@ pub trait Client: Sync + Send {
if let Some(proxy) = extra.and_then(|v| v.proxy.as_deref()) {
builder = set_proxy(builder, proxy)?;
}
if let Some(user_agent) = self.global_config().read().user_agent.as_ref() {
if let Some(user_agent) = self.app_config().user_agent.as_ref() {
builder = builder.user_agent(user_agent);
}
let client = builder
@@ -69,7 +70,7 @@ pub trait Client: Sync + Send {
}
async fn chat_completions(&self, input: Input) -> Result<ChatCompletionsOutput> {
if self.global_config().read().dry_run {
if self.app_config().dry_run {
let content = input.echo_messages();
return Ok(ChatCompletionsOutput::new(&content));
}
@@ -89,7 +90,7 @@ pub trait Client: Sync + Send {
let input = input.clone();
tokio::select! {
ret = async {
if self.global_config().read().dry_run {
if self.app_config().dry_run {
let content = input.echo_messages();
handler.text(&content)?;
return Ok(());
@@ -413,9 +414,10 @@ pub async fn call_chat_completions(
print: bool,
extract_code: bool,
client: &dyn Client,
ctx: &mut RequestContext,
abort_signal: AbortSignal,
) -> Result<(String, Vec<ToolResult>)> {
let is_child_agent = client.global_config().read().current_depth > 0;
let is_child_agent = ctx.current_depth > 0;
let spinner_message = if is_child_agent { "" } else { "Generating" };
let ret = abortable_run_with_spinner(
client.chat_completions(input.clone()),
@@ -436,15 +438,13 @@ pub async fn call_chat_completions(
text = extract_code_block(&strip_think_tag(&text)).to_string();
}
if print {
client.global_config().read().print_markdown(&text)?;
ctx.app.config.print_markdown(&text)?;
}
}
let tool_results = eval_tool_calls(client.global_config(), tool_calls).await?;
if let Some(tracker) = client.global_config().write().tool_call_tracker.as_mut() {
tool_results
.iter()
.for_each(|res| tracker.record_call(res.call.clone()));
}
let tool_results = eval_tool_calls(ctx, tool_calls).await?;
tool_results
.iter()
.for_each(|res| ctx.tool_scope.tool_tracker.record_call(res.call.clone()));
Ok((text, tool_results))
}
Err(err) => Err(err),
@@ -454,6 +454,7 @@ pub async fn call_chat_completions(
pub async fn call_chat_completions_streaming(
input: &Input,
client: &dyn Client,
ctx: &mut RequestContext,
abort_signal: AbortSignal,
) -> Result<(String, Vec<ToolResult>)> {
let (tx, rx) = unbounded_channel();
@@ -461,7 +462,7 @@ pub async fn call_chat_completions_streaming(
let (send_ret, render_ret) = tokio::join!(
client.chat_completions_streaming(input, &mut handler),
render_stream(rx, client.global_config(), abort_signal.clone()),
render_stream(rx, client.app_config(), abort_signal.clone()),
);
if handler.abort().aborted() {
@@ -476,12 +477,10 @@ pub async fn call_chat_completions_streaming(
if !text.is_empty() && !text.ends_with('\n') {
println!();
}
let tool_results = eval_tool_calls(client.global_config(), tool_calls).await?;
if let Some(tracker) = client.global_config().write().tool_call_tracker.as_mut() {
tool_results
.iter()
.for_each(|res| tracker.record_call(res.call.clone()));
}
let tool_results = eval_tool_calls(ctx, tool_calls).await?;
tool_results
.iter()
.for_each(|res| ctx.tool_scope.tool_tracker.record_call(res.call.clone()));
Ok((text, tool_results))
}
Err(err) => {