mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
moving to headers
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user