This PR does two things because after I got deep into the first one I started pulling on the thread to the second: - Makes `ConversationManager` the place where all in-memory conversations are created and stored. Previously, `MessageProcessor` in the `codex-mcp-server` crate was doing this via its `session_map`, but this is something that should be done in `codex-core`. - It unwinds the `ctrl_c: tokio::sync::Notify` that was threaded throughout our code. I think this made sense at one time, but now that we handle Ctrl-C within the TUI and have a proper `Op::Interrupt` event, I don't think this was quite right, so I removed it. For `codex exec` and `codex proto`, we now use `tokio::signal::ctrl_c()` directly, but we no longer make `Notify` a field of `Codex` or `CodexConversation`. Changes of note: - Adds the files `conversation_manager.rs` and `codex_conversation.rs` to `codex-core`. - `Codex` and `CodexSpawnOk` are no longer exported from `codex-core`: other crates must use `CodexConversation` instead (which is created via `ConversationManager`). - `core/src/codex_wrapper.rs` has been deleted in favor of `ConversationManager`. - `ConversationManager::new_conversation()` returns `NewConversation`, which is in line with the `new_conversation` tool we want to add to the MCP server. Note `NewConversation` includes `SessionConfiguredEvent`, so we eliminate checks in cases like `codex-rs/core/tests/client.rs` to verify `SessionConfiguredEvent` is the first event because that is now internal to `ConversationManager`. - Quite a bit of code was deleted from `codex-rs/mcp-server/src/message_processor.rs` since it no longer has to manage multiple conversations itself: it goes through `ConversationManager` instead. - `core/tests/live_agent.rs` has been deleted because I had to update a bunch of tests and all the tests in here were ignored, and I don't think anyone ever ran them, so this was just technical debt, at this point. - Removed `notify_on_sigint()` from `util.rs` (and in a follow-up, I hope to refactor the blandly-named `util.rs` into more descriptive files). - In general, I started replacing local variables named `codex` as `conversation`, where appropriate, though admittedly I didn't do it through all the integration tests because that would have added a lot of noise to this PR. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/2240). * #2264 * #2263 * __->__ #2240
45 lines
1.4 KiB
Rust
45 lines
1.4 KiB
Rust
use std::path::Path;
|
||
use std::time::Duration;
|
||
|
||
use rand::Rng;
|
||
|
||
const INITIAL_DELAY_MS: u64 = 200;
|
||
const BACKOFF_FACTOR: f64 = 2.0;
|
||
|
||
pub(crate) fn backoff(attempt: u64) -> Duration {
|
||
let exp = BACKOFF_FACTOR.powi(attempt.saturating_sub(1) as i32);
|
||
let base = (INITIAL_DELAY_MS as f64 * exp) as u64;
|
||
let jitter = rand::rng().random_range(0.9..1.1);
|
||
Duration::from_millis((base as f64 * jitter) as u64)
|
||
}
|
||
|
||
/// Return `true` if the project folder specified by the `Config` is inside a
|
||
/// Git repository.
|
||
///
|
||
/// The check walks up the directory hierarchy looking for a `.git` file or
|
||
/// directory (note `.git` can be a file that contains a `gitdir` entry). This
|
||
/// approach does **not** require the `git` binary or the `git2` crate and is
|
||
/// therefore fairly lightweight.
|
||
///
|
||
/// Note that this does **not** detect *work‑trees* created with
|
||
/// `git worktree add` where the checkout lives outside the main repository
|
||
/// directory. If you need Codex to work from such a checkout simply pass the
|
||
/// `--allow-no-git-exec` CLI flag that disables the repo requirement.
|
||
pub fn is_inside_git_repo(base_dir: &Path) -> bool {
|
||
let mut dir = base_dir.to_path_buf();
|
||
|
||
loop {
|
||
if dir.join(".git").exists() {
|
||
return true;
|
||
}
|
||
|
||
// Pop one component (go up one directory). `pop` returns false when
|
||
// we have reached the filesystem root.
|
||
if !dir.pop() {
|
||
break;
|
||
}
|
||
}
|
||
|
||
false
|
||
}
|