moving to headers

This commit is contained in:
pash
2026-01-30 08:38:04 -08:00
parent 9eff9b835e
commit 024f49e63e
3 changed files with 52 additions and 14 deletions

View File

@@ -513,6 +513,8 @@ pub(crate) struct TurnContext {
pub(crate) turn_metadata_header: Option<String>,
}
const TURN_METADATA_TIMEOUT: TokioDuration = TokioDuration::from_millis(150);
impl TurnContext {
pub(crate) fn resolve_path(&self, path: Option<String>) -> PathBuf {
path.as_ref()
@@ -734,7 +736,7 @@ impl Session {
// On some CI environments (notably Windows), git commands can hang
// until their timeout elapses. Cap the total time we spend gathering
// optional metadata so turn startup stays responsive.
timeout(TokioDuration::from_millis(750), async {
timeout(TURN_METADATA_TIMEOUT, async {
let git_info = collect_git_info(cwd).await?;
let latest_git_commit_hash = git_info.commit_hash;
let associated_remote_urls = get_git_remote_urls(cwd).await;
@@ -757,6 +759,20 @@ impl Session {
.flatten()
}
async fn get_or_build_turn_metadata_header(&self, cwd: &Path) -> Option<String> {
if let Some(cached) = {
let state = self.state.lock().await;
state.cached_turn_metadata_header(cwd)
} {
return cached;
}
let header = Self::build_turn_metadata_header(cwd).await;
let mut state = self.state.lock().await;
state.set_turn_metadata_header_cache(cwd, header.clone());
header
}
#[allow(clippy::too_many_arguments)]
async fn new(
mut session_configuration: SessionConfiguration,
@@ -1293,8 +1309,9 @@ impl Session {
if let Some(final_schema) = final_output_json_schema {
turn_context.final_output_json_schema = final_schema;
}
turn_context.turn_metadata_header =
Self::build_turn_metadata_header(turn_context.cwd.as_path()).await;
turn_context.turn_metadata_header = self
.get_or_build_turn_metadata_header(turn_context.cwd.as_path())
.await;
Arc::new(turn_context)
}
@@ -3250,8 +3267,9 @@ async fn spawn_review_thread(
parent_turn_context.client.transport_manager(),
);
let turn_metadata_header =
Session::build_turn_metadata_header(parent_turn_context.cwd.as_path()).await;
let turn_metadata_header = sess
.get_or_build_turn_metadata_header(parent_turn_context.cwd.as_path())
.await;
let review_turn_context = TurnContext {
sub_id: sub_id.to_string(),
client,

View File

@@ -128,11 +128,19 @@ pub async fn get_git_remote_urls(cwd: &Path) -> Option<BTreeMap<String, String>>
let stdout = String::from_utf8(output.stdout).ok()?;
let mut remotes = BTreeMap::new();
for line in stdout.lines() {
if !line.contains("(fetch)") {
let Some(fetch_line) = line.strip_suffix(" (fetch)") else {
continue;
}
let mut parts = line.split_whitespace();
if let (Some(name), Some(url)) = (parts.next(), parts.next()) {
};
let Some((name, url_part)) = fetch_line
.split_once('\t')
.or_else(|| fetch_line.split_once(' '))
else {
continue;
};
let url = url_part.trim_start();
if !url.is_empty() {
remotes.insert(name.to_string(), url.to_string());
}
}
@@ -220,11 +228,10 @@ pub async fn git_diff_to_remote(cwd: &Path) -> Option<GitDiffToRemote> {
/// Run a git command with a timeout to prevent blocking on large repositories
async fn run_git_command_with_timeout(args: &[&str], cwd: &Path) -> Option<std::process::Output> {
let result = timeout(
GIT_COMMAND_TIMEOUT,
Command::new("git").args(args).current_dir(cwd).output(),
)
.await;
let mut command = Command::new("git");
command.args(args).current_dir(cwd);
command.kill_on_drop(true);
let result = timeout(GIT_COMMAND_TIMEOUT, command.output()).await;
match result {
Ok(Ok(output)) => Some(output),

View File

@@ -3,6 +3,7 @@
use codex_protocol::models::ResponseItem;
use std::collections::HashMap;
use std::collections::HashSet;
use std::path::Path;
use crate::codex::SessionConfiguration;
use crate::context_manager::ContextManager;
@@ -19,6 +20,7 @@ pub(crate) struct SessionState {
pub(crate) server_reasoning_included: bool,
pub(crate) dependency_env: HashMap<String, String>,
pub(crate) mcp_dependency_prompted: HashSet<String>,
pub(crate) turn_metadata_header_cache: HashMap<String, Option<String>>,
/// Whether the session's initial context has been seeded into history.
///
/// TODO(owen): This is a temporary solution to avoid updating a thread's updated_at
@@ -37,6 +39,7 @@ impl SessionState {
server_reasoning_included: false,
dependency_env: HashMap::new(),
mcp_dependency_prompted: HashSet::new(),
turn_metadata_header_cache: HashMap::new(),
initial_context_seeded: false,
}
}
@@ -125,6 +128,16 @@ impl SessionState {
pub(crate) fn dependency_env(&self) -> HashMap<String, String> {
self.dependency_env.clone()
}
pub(crate) fn cached_turn_metadata_header(&self, cwd: &Path) -> Option<Option<String>> {
let key = cwd.to_string_lossy().into_owned();
self.turn_metadata_header_cache.get(&key).cloned()
}
pub(crate) fn set_turn_metadata_header_cache(&mut self, cwd: &Path, header: Option<String>) {
let key = cwd.to_string_lossy().into_owned();
self.turn_metadata_header_cache.insert(key, header);
}
}
// Sometimes new snapshots don't include credits or plan information.