mirror of
https://github.com/openai/codex.git
synced 2026-05-22 20:14:17 +00:00
Compare commits
1 Commits
dev/bookho
...
starr/app-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e66b5e189 |
@@ -409,6 +409,7 @@ impl InProcessClientStartArgs {
|
||||
config_warnings: self.config_warnings,
|
||||
session_source: self.session_source,
|
||||
enable_codex_api_key_env: self.enable_codex_api_key_env,
|
||||
plugin_startup_tasks: codex_app_server::PluginStartupTasks::Start,
|
||||
initialize,
|
||||
channel_capacity: self.channel_capacity,
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ use tracing::warn;
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct ConfigManager {
|
||||
codex_home: PathBuf,
|
||||
process_cwd: Option<PathBuf>,
|
||||
cli_overrides: Arc<RwLock<Vec<(String, TomlValue)>>>,
|
||||
runtime_feature_enablement: Arc<RwLock<BTreeMap<String, bool>>>,
|
||||
loader_overrides: LoaderOverrides,
|
||||
@@ -38,6 +39,7 @@ pub(crate) struct ConfigManager {
|
||||
impl ConfigManager {
|
||||
pub(crate) fn new(
|
||||
codex_home: PathBuf,
|
||||
process_cwd: Option<PathBuf>,
|
||||
cli_overrides: Vec<(String, TomlValue)>,
|
||||
loader_overrides: LoaderOverrides,
|
||||
cloud_requirements: CloudRequirementsLoader,
|
||||
@@ -46,6 +48,7 @@ impl ConfigManager {
|
||||
) -> Self {
|
||||
Self {
|
||||
codex_home,
|
||||
process_cwd,
|
||||
cli_overrides: Arc::new(RwLock::new(cli_overrides)),
|
||||
runtime_feature_enablement: Arc::new(RwLock::new(BTreeMap::new())),
|
||||
loader_overrides,
|
||||
@@ -218,7 +221,7 @@ impl ConfigManager {
|
||||
.cli_overrides(merged_cli_overrides)
|
||||
.loader_overrides(self.loader_overrides.clone())
|
||||
.harness_overrides(typesafe_overrides)
|
||||
.fallback_cwd(fallback_cwd)
|
||||
.fallback_cwd(fallback_cwd.or_else(|| self.process_cwd.clone()))
|
||||
.cloud_requirements(self.current_cloud_requirements())
|
||||
.thread_config_loader(self.current_thread_config_loader())
|
||||
.build()
|
||||
@@ -278,6 +281,7 @@ impl ConfigManager {
|
||||
) -> Self {
|
||||
Self::new(
|
||||
codex_home,
|
||||
/*process_cwd*/ None,
|
||||
cli_overrides,
|
||||
loader_overrides,
|
||||
cloud_requirements,
|
||||
|
||||
@@ -137,6 +137,8 @@ pub struct InProcessStartArgs {
|
||||
pub session_source: SessionSource,
|
||||
/// Whether auth loading should honor the `CODEX_API_KEY` environment variable.
|
||||
pub enable_codex_api_key_env: bool,
|
||||
/// Whether plugin startup tasks should run when the embedded runtime starts.
|
||||
pub plugin_startup_tasks: crate::PluginStartupTasks,
|
||||
/// Initialize params used for initial handshake.
|
||||
pub initialize: InitializeParams,
|
||||
/// Capacity used for all runtime queues (clamped to at least 1).
|
||||
@@ -194,13 +196,20 @@ pub struct InProcessClientSender {
|
||||
}
|
||||
|
||||
impl InProcessClientSender {
|
||||
pub async fn request(&self, request: ClientRequest) -> IoResult<PendingClientRequestResponse> {
|
||||
fn send_request(
|
||||
&self,
|
||||
request: ClientRequest,
|
||||
) -> IoResult<oneshot::Receiver<PendingClientRequestResponse>> {
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
self.try_send_client_message(InProcessClientMessage::Request {
|
||||
request: Box::new(request),
|
||||
response_tx,
|
||||
})?;
|
||||
response_rx.await.map_err(|err| {
|
||||
Ok(response_rx)
|
||||
}
|
||||
|
||||
pub async fn request(&self, request: ClientRequest) -> IoResult<PendingClientRequestResponse> {
|
||||
self.send_request(request)?.await.map_err(|err| {
|
||||
IoError::new(
|
||||
ErrorKind::BrokenPipe,
|
||||
format!("in-process request response channel closed: {err}"),
|
||||
@@ -259,6 +268,17 @@ pub struct InProcessClientHandle {
|
||||
}
|
||||
|
||||
impl InProcessClientHandle {
|
||||
/// Queues a typed client request and returns a receiver for its response.
|
||||
///
|
||||
/// Use this when a caller must preserve request submission order while
|
||||
/// awaiting responses later.
|
||||
pub fn send_request(
|
||||
&self,
|
||||
request: ClientRequest,
|
||||
) -> IoResult<oneshot::Receiver<PendingClientRequestResponse>> {
|
||||
self.client.send_request(request)
|
||||
}
|
||||
|
||||
/// Sends a typed client request into the in-process runtime.
|
||||
///
|
||||
/// The returned value is a transport-level `IoResult` containing either a
|
||||
@@ -343,15 +363,8 @@ impl InProcessClientHandle {
|
||||
/// the handle, so callers receive a ready-to-use runtime. If initialize fails,
|
||||
/// the runtime is shut down and an `InvalidData` error is returned.
|
||||
pub async fn start(args: InProcessStartArgs) -> IoResult<InProcessClientHandle> {
|
||||
let initialize = args.initialize.clone();
|
||||
let client = start_uninitialized(args).await?;
|
||||
|
||||
let initialize_response = client
|
||||
.request(ClientRequest::Initialize {
|
||||
request_id: RequestId::Integer(0),
|
||||
params: initialize,
|
||||
})
|
||||
.await?;
|
||||
let (client, initialize_response) =
|
||||
start_with_initialize_response(args, RequestId::Integer(0)).await?;
|
||||
if let Err(error) = initialize_response {
|
||||
let _ = client.shutdown().await;
|
||||
return Err(IoError::new(
|
||||
@@ -359,11 +372,37 @@ pub async fn start(args: InProcessStartArgs) -> IoResult<InProcessClientHandle>
|
||||
format!("in-process initialize failed: {}", error.message),
|
||||
));
|
||||
}
|
||||
client.notify(ClientNotification::Initialized)?;
|
||||
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
/// Starts an in-process app-server runtime and returns the initialize result.
|
||||
///
|
||||
/// The returned client is only ready for normal requests when initialize
|
||||
/// succeeds. On success this sends `initialized` before returning; on failure
|
||||
/// the caller owns shutdown so tests can inspect the structured initialize
|
||||
/// error before dropping the runtime.
|
||||
pub async fn start_with_initialize_response(
|
||||
args: InProcessStartArgs,
|
||||
request_id: RequestId,
|
||||
) -> IoResult<(
|
||||
InProcessClientHandle,
|
||||
std::result::Result<Result, JSONRPCErrorError>,
|
||||
)> {
|
||||
let initialize = args.initialize.clone();
|
||||
let client = start_uninitialized(args).await?;
|
||||
let initialize_response = client
|
||||
.request(ClientRequest::Initialize {
|
||||
request_id,
|
||||
params: initialize,
|
||||
})
|
||||
.await?;
|
||||
if initialize_response.is_ok() {
|
||||
client.notify(ClientNotification::Initialized)?;
|
||||
}
|
||||
Ok((client, initialize_response))
|
||||
}
|
||||
|
||||
async fn start_uninitialized(args: InProcessStartArgs) -> IoResult<InProcessClientHandle> {
|
||||
let channel_capacity = args.channel_capacity.max(1);
|
||||
let installation_id = resolve_installation_id(&args.config.codex_home).await?;
|
||||
@@ -407,6 +446,7 @@ async fn start_uninitialized(args: InProcessStartArgs) -> IoResult<InProcessClie
|
||||
let processor_outgoing = Arc::clone(&outgoing_message_sender);
|
||||
let config_manager = ConfigManager::new(
|
||||
args.config.codex_home.to_path_buf(),
|
||||
Some(args.config.cwd.to_path_buf()),
|
||||
args.cli_overrides,
|
||||
args.loader_overrides,
|
||||
args.cloud_requirements,
|
||||
@@ -431,7 +471,7 @@ async fn start_uninitialized(args: InProcessStartArgs) -> IoResult<InProcessClie
|
||||
installation_id,
|
||||
rpc_transport: AppServerRpcTransport::InProcess,
|
||||
remote_control_handle: None,
|
||||
plugin_startup_tasks: crate::PluginStartupTasks::Start,
|
||||
plugin_startup_tasks: args.plugin_startup_tasks,
|
||||
}));
|
||||
let mut thread_created_rx = processor.thread_created_receiver();
|
||||
let session = Arc::new(ConnectionSessionState::new());
|
||||
@@ -512,8 +552,10 @@ async fn start_uninitialized(args: InProcessStartArgs) -> IoResult<InProcessClie
|
||||
processor.drain_background_tasks().await;
|
||||
processor.shutdown_threads().await;
|
||||
});
|
||||
let mut pending_request_responses =
|
||||
HashMap::<RequestId, oneshot::Sender<PendingClientRequestResponse>>::new();
|
||||
let mut pending_request_responses = HashMap::<
|
||||
RequestId,
|
||||
oneshot::Sender<std::result::Result<Result, JSONRPCErrorError>>,
|
||||
>::new();
|
||||
let mut shutdown_ack = None;
|
||||
|
||||
loop {
|
||||
@@ -774,6 +816,7 @@ mod tests {
|
||||
config_warnings: Vec::new(),
|
||||
session_source,
|
||||
enable_codex_api_key_env: false,
|
||||
plugin_startup_tasks: crate::PluginStartupTasks::Start,
|
||||
initialize: InitializeParams {
|
||||
client_info: ClientInfo {
|
||||
name: "codex-in-process-test".to_string(),
|
||||
|
||||
@@ -460,6 +460,7 @@ pub async fn run_main_with_transport_options(
|
||||
.map_err(std::io::Error::other)?;
|
||||
let config_manager = ConfigManager::new(
|
||||
codex_home.to_path_buf(),
|
||||
/*process_cwd*/ None,
|
||||
cli_kv_overrides.clone(),
|
||||
loader_overrides,
|
||||
Default::default(),
|
||||
|
||||
@@ -205,6 +205,7 @@ mod tests {
|
||||
});
|
||||
let config_manager = ConfigManager::new(
|
||||
temp_dir.path().to_path_buf(),
|
||||
/*process_cwd*/ None,
|
||||
Vec::new(),
|
||||
LoaderOverrides::without_managed_config_for_tests(),
|
||||
CloudRequirementsLoader::default(),
|
||||
|
||||
@@ -237,6 +237,7 @@ async fn build_test_processor(
|
||||
AuthManager::shared_from_config(config.as_ref(), /*enable_codex_api_key_env*/ false).await;
|
||||
let config_manager = ConfigManager::new(
|
||||
config.codex_home.to_path_buf(),
|
||||
/*process_cwd*/ None,
|
||||
Vec::new(),
|
||||
LoaderOverrides::default(),
|
||||
CloudRequirementsLoader::default(),
|
||||
|
||||
@@ -580,6 +580,7 @@ mod thread_processor_behavior_tests {
|
||||
};
|
||||
let config_manager = ConfigManager::new(
|
||||
temp_dir.path().to_path_buf(),
|
||||
/*process_cwd*/ None,
|
||||
Vec::new(),
|
||||
LoaderOverrides::default(),
|
||||
CloudRequirementsLoader::default(),
|
||||
|
||||
@@ -16,10 +16,14 @@ workspace = true
|
||||
anyhow = { workspace = true }
|
||||
base64 = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
codex-app-server = { workspace = true }
|
||||
codex-app-server-protocol = { workspace = true }
|
||||
codex-arg0 = { workspace = true }
|
||||
codex-config = { workspace = true }
|
||||
codex-core = { workspace = true }
|
||||
codex-exec-server = { workspace = true }
|
||||
codex-features = { workspace = true }
|
||||
codex-feedback = { workspace = true }
|
||||
codex-login = { workspace = true }
|
||||
codex-models-manager = { workspace = true }
|
||||
codex-protocol = { workspace = true }
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Stdio;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicI64;
|
||||
use std::sync::atomic::Ordering;
|
||||
use tokio::io::AsyncBufReadExt;
|
||||
@@ -9,12 +11,18 @@ use tokio::io::BufReader;
|
||||
use tokio::process::Child;
|
||||
use tokio::process::ChildStdin;
|
||||
use tokio::process::ChildStdout;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use anyhow::Context;
|
||||
use codex_app_server::PluginStartupTasks;
|
||||
use codex_app_server::in_process;
|
||||
use codex_app_server::in_process::InProcessClientHandle;
|
||||
use codex_app_server::in_process::InProcessServerEvent;
|
||||
use codex_app_server_protocol::AppsListParams;
|
||||
use codex_app_server_protocol::CancelLoginAccountParams;
|
||||
use codex_app_server_protocol::ClientInfo;
|
||||
use codex_app_server_protocol::ClientNotification;
|
||||
use codex_app_server_protocol::ClientRequest;
|
||||
use codex_app_server_protocol::CollaborationModeListParams;
|
||||
use codex_app_server_protocol::CommandExecParams;
|
||||
use codex_app_server_protocol::CommandExecResizeParams;
|
||||
@@ -98,11 +106,36 @@ use codex_app_server_protocol::TurnInterruptParams;
|
||||
use codex_app_server_protocol::TurnStartParams;
|
||||
use codex_app_server_protocol::TurnSteerParams;
|
||||
use codex_app_server_protocol::WindowsSandboxSetupStartParams;
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_config::CloudRequirementsLoader;
|
||||
use codex_config::LoaderOverrides;
|
||||
use codex_core::config::ConfigBuilder;
|
||||
use codex_exec_server::EnvironmentManager;
|
||||
use codex_feedback::CodexFeedback;
|
||||
use codex_login::default_client::CODEX_INTERNAL_ORIGINATOR_OVERRIDE_ENV_VAR;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use tokio::process::Command;
|
||||
|
||||
pub struct McpProcess {
|
||||
pub struct AppServerTestProcess {
|
||||
next_request_id: AtomicI64,
|
||||
backend: AppServerBackend,
|
||||
pending_messages: VecDeque<JSONRPCMessage>,
|
||||
}
|
||||
|
||||
enum AppServerBackend {
|
||||
Child(Box<ChildAppServerProcess>),
|
||||
InProcessPending {
|
||||
codex_home: PathBuf,
|
||||
loader_overrides: LoaderOverrides,
|
||||
},
|
||||
InProcessRunning {
|
||||
client: Option<InProcessClientHandle>,
|
||||
response_tx: mpsc::UnboundedSender<JSONRPCMessage>,
|
||||
response_rx: mpsc::UnboundedReceiver<JSONRPCMessage>,
|
||||
},
|
||||
}
|
||||
|
||||
struct ChildAppServerProcess {
|
||||
/// Retain this child process until the client is dropped. The Tokio runtime
|
||||
/// will make a "best effort" to reap the process after it exits, but it is
|
||||
/// not a guarantee. See the `kill_on_drop` documentation for details.
|
||||
@@ -110,18 +143,42 @@ pub struct McpProcess {
|
||||
process: Child,
|
||||
stdin: Option<ChildStdin>,
|
||||
stdout: BufReader<ChildStdout>,
|
||||
pending_messages: VecDeque<JSONRPCMessage>,
|
||||
}
|
||||
|
||||
pub const DEFAULT_CLIENT_NAME: &str = "codex-app-server-tests";
|
||||
pub const DISABLE_PLUGIN_STARTUP_TASKS_ARG: &str = "--disable-plugin-startup-tasks-for-tests";
|
||||
const DISABLE_MANAGED_CONFIG_ENV_VAR: &str = "CODEX_APP_SERVER_DISABLE_MANAGED_CONFIG";
|
||||
|
||||
impl McpProcess {
|
||||
impl AppServerTestProcess {
|
||||
pub async fn new(codex_home: &Path) -> anyhow::Result<Self> {
|
||||
Self::new_with_env_and_args(codex_home, &[], &[DISABLE_PLUGIN_STARTUP_TASKS_ARG]).await
|
||||
}
|
||||
|
||||
pub async fn new_in_process(codex_home: &Path) -> anyhow::Result<Self> {
|
||||
let loader_overrides = LoaderOverrides::with_managed_config_path_for_tests(
|
||||
codex_home.join("managed_config.toml"),
|
||||
);
|
||||
Ok(Self::new_pending_in_process(codex_home, loader_overrides))
|
||||
}
|
||||
|
||||
pub async fn new_in_process_without_managed_config(codex_home: &Path) -> anyhow::Result<Self> {
|
||||
Ok(Self::new_pending_in_process(
|
||||
codex_home,
|
||||
LoaderOverrides::default(),
|
||||
))
|
||||
}
|
||||
|
||||
fn new_pending_in_process(codex_home: &Path, loader_overrides: LoaderOverrides) -> Self {
|
||||
Self {
|
||||
next_request_id: AtomicI64::new(0),
|
||||
backend: AppServerBackend::InProcessPending {
|
||||
codex_home: codex_home.to_path_buf(),
|
||||
loader_overrides,
|
||||
},
|
||||
pending_messages: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn new_without_managed_config(codex_home: &Path) -> anyhow::Result<Self> {
|
||||
Self::new_with_env(codex_home, &[(DISABLE_MANAGED_CONFIG_ENV_VAR, Some("1"))]).await
|
||||
}
|
||||
@@ -152,7 +209,7 @@ impl McpProcess {
|
||||
Self::new_with_env_and_args(codex_home, &[], &all_args).await
|
||||
}
|
||||
|
||||
/// Creates a new MCP process, allowing tests to override or remove
|
||||
/// Creates a new app-server child process, allowing tests to override or remove
|
||||
/// specific environment variables for the child process only.
|
||||
///
|
||||
/// Pass a tuple of (key, Some(value)) to set/override, or (key, None) to
|
||||
@@ -206,15 +263,15 @@ impl McpProcess {
|
||||
let mut process = cmd
|
||||
.kill_on_drop(true)
|
||||
.spawn()
|
||||
.context("codex-mcp-server proc should start")?;
|
||||
.context("codex-app-server proc should start")?;
|
||||
let stdin = process
|
||||
.stdin
|
||||
.take()
|
||||
.ok_or_else(|| anyhow::format_err!("mcp should have stdin fd"))?;
|
||||
.ok_or_else(|| anyhow::format_err!("app-server should have stdin fd"))?;
|
||||
let stdout = process
|
||||
.stdout
|
||||
.take()
|
||||
.ok_or_else(|| anyhow::format_err!("mcp should have stdout fd"))?;
|
||||
.ok_or_else(|| anyhow::format_err!("app-server should have stdout fd"))?;
|
||||
let stdout = BufReader::new(stdout);
|
||||
|
||||
// Forward child's stderr to our stderr so failures are visible even
|
||||
@@ -223,20 +280,22 @@ impl McpProcess {
|
||||
let mut stderr_reader = BufReader::new(stderr).lines();
|
||||
tokio::spawn(async move {
|
||||
while let Ok(Some(line)) = stderr_reader.next_line().await {
|
||||
eprintln!("[mcp stderr] {line}");
|
||||
eprintln!("[app-server stderr] {line}");
|
||||
}
|
||||
});
|
||||
}
|
||||
Ok(Self {
|
||||
next_request_id: AtomicI64::new(0),
|
||||
process,
|
||||
stdin: Some(stdin),
|
||||
stdout,
|
||||
backend: AppServerBackend::Child(Box::new(ChildAppServerProcess {
|
||||
process,
|
||||
stdin: Some(stdin),
|
||||
stdout,
|
||||
})),
|
||||
pending_messages: VecDeque::new(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Performs the initialization handshake with the MCP server.
|
||||
/// Performs the initialization handshake with the app-server.
|
||||
pub async fn initialize(&mut self) -> anyhow::Result<()> {
|
||||
let initialized = self
|
||||
.initialize_with_client_info(ClientInfo {
|
||||
@@ -282,6 +341,37 @@ impl McpProcess {
|
||||
&mut self,
|
||||
params: InitializeParams,
|
||||
) -> anyhow::Result<JSONRPCMessage> {
|
||||
if let AppServerBackend::InProcessPending {
|
||||
codex_home,
|
||||
loader_overrides,
|
||||
} = &self.backend
|
||||
{
|
||||
let request_id = self.next_request_id.fetch_add(1, Ordering::Relaxed);
|
||||
let start_args =
|
||||
build_in_process_start_args(codex_home, loader_overrides, params).await?;
|
||||
let (client, initialize_response) = in_process::start_with_initialize_response(
|
||||
start_args,
|
||||
RequestId::Integer(request_id),
|
||||
)
|
||||
.await?;
|
||||
let (response_tx, response_rx) = mpsc::unbounded_channel();
|
||||
self.backend = AppServerBackend::InProcessRunning {
|
||||
client: Some(client),
|
||||
response_tx,
|
||||
response_rx,
|
||||
};
|
||||
return Ok(match initialize_response {
|
||||
Ok(result) => JSONRPCMessage::Response(JSONRPCResponse {
|
||||
id: RequestId::Integer(request_id),
|
||||
result,
|
||||
}),
|
||||
Err(error) => JSONRPCMessage::Error(JSONRPCError {
|
||||
id: RequestId::Integer(request_id),
|
||||
error,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
let params = Some(serde_json::to_value(params)?);
|
||||
let request_id = self.send_request("initialize", params).await?;
|
||||
let message = self.read_jsonrpc_message().await?;
|
||||
@@ -1189,7 +1279,46 @@ impl McpProcess {
|
||||
params,
|
||||
trace: None,
|
||||
});
|
||||
self.send_jsonrpc_message(message).await?;
|
||||
match &mut self.backend {
|
||||
AppServerBackend::Child(_) => self.send_jsonrpc_message(message).await?,
|
||||
AppServerBackend::InProcessPending { .. } => {
|
||||
anyhow::bail!("in-process app-server is not initialized");
|
||||
}
|
||||
AppServerBackend::InProcessRunning {
|
||||
client,
|
||||
response_tx,
|
||||
..
|
||||
} => {
|
||||
let JSONRPCMessage::Request(request) = message else {
|
||||
unreachable!("send_request always constructs a request");
|
||||
};
|
||||
let request =
|
||||
serde_json::from_value::<ClientRequest>(serde_json::to_value(request)?)?;
|
||||
let response_rx = in_process_client(client)?.send_request(request)?;
|
||||
let response_tx = response_tx.clone();
|
||||
tokio::spawn(async move {
|
||||
let message = match response_rx.await {
|
||||
Ok(Ok(result)) => JSONRPCMessage::Response(JSONRPCResponse {
|
||||
id: RequestId::Integer(request_id),
|
||||
result,
|
||||
}),
|
||||
Ok(Err(error)) => JSONRPCMessage::Error(JSONRPCError {
|
||||
id: RequestId::Integer(request_id),
|
||||
error,
|
||||
}),
|
||||
Err(error) => JSONRPCMessage::Error(JSONRPCError {
|
||||
id: RequestId::Integer(request_id),
|
||||
error: JSONRPCErrorError {
|
||||
code: -32000,
|
||||
message: error.to_string(),
|
||||
data: None,
|
||||
},
|
||||
}),
|
||||
};
|
||||
let _ = response_tx.send(message);
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(request_id)
|
||||
}
|
||||
|
||||
@@ -1228,9 +1357,33 @@ impl McpProcess {
|
||||
}
|
||||
|
||||
async fn send_jsonrpc_message(&mut self, message: JSONRPCMessage) -> anyhow::Result<()> {
|
||||
if let AppServerBackend::InProcessRunning { client, .. } = &self.backend {
|
||||
let client = in_process_client(client)?;
|
||||
match message {
|
||||
JSONRPCMessage::Response(response) => {
|
||||
client.respond_to_server_request(response.id, response.result)?;
|
||||
}
|
||||
JSONRPCMessage::Error(error) => {
|
||||
client.fail_server_request(error.id, error.error)?;
|
||||
}
|
||||
JSONRPCMessage::Notification(notification) => {
|
||||
let notification = serde_json::from_value::<ClientNotification>(
|
||||
serde_json::to_value(notification)?,
|
||||
)?;
|
||||
client.notify(notification)?;
|
||||
}
|
||||
JSONRPCMessage::Request(_) => {
|
||||
anyhow::bail!("use send_request for in-process client requests");
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
eprintln!("writing message to stdin: {message:?}");
|
||||
let Some(stdin) = self.stdin.as_mut() else {
|
||||
anyhow::bail!("mcp stdin closed");
|
||||
let AppServerBackend::Child(child) = &mut self.backend else {
|
||||
unreachable!("in-process path returned above");
|
||||
};
|
||||
let Some(stdin) = child.stdin.as_mut() else {
|
||||
anyhow::bail!("app-server stdin closed");
|
||||
};
|
||||
let payload = serde_json::to_string(&message)?;
|
||||
stdin.write_all(payload.as_bytes()).await?;
|
||||
@@ -1240,8 +1393,45 @@ impl McpProcess {
|
||||
}
|
||||
|
||||
async fn read_jsonrpc_message(&mut self) -> anyhow::Result<JSONRPCMessage> {
|
||||
if let AppServerBackend::InProcessRunning {
|
||||
client,
|
||||
response_rx,
|
||||
..
|
||||
} = &mut self.backend
|
||||
{
|
||||
let client = client
|
||||
.as_mut()
|
||||
.ok_or_else(|| anyhow::format_err!("in-process app-server is closed"))?;
|
||||
loop {
|
||||
tokio::select! {
|
||||
response = response_rx.recv() => {
|
||||
let Some(message) = response else {
|
||||
anyhow::bail!("in-process response channel closed");
|
||||
};
|
||||
return Ok(message);
|
||||
}
|
||||
event = client.next_event() => {
|
||||
let Some(event) = event else {
|
||||
anyhow::bail!("in-process app-server event stream closed");
|
||||
};
|
||||
match event {
|
||||
InProcessServerEvent::ServerRequest(request) => {
|
||||
return Ok(serde_json::from_value(serde_json::to_value(request)?)?);
|
||||
}
|
||||
InProcessServerEvent::ServerNotification(notification) => {
|
||||
return Ok(serde_json::from_value(serde_json::to_value(notification)?)?);
|
||||
}
|
||||
InProcessServerEvent::Lagged { .. } => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut line = String::new();
|
||||
self.stdout.read_line(&mut line).await?;
|
||||
let AppServerBackend::Child(child) = &mut self.backend else {
|
||||
unreachable!("in-process path returned above");
|
||||
};
|
||||
child.stdout.read_line(&mut line).await?;
|
||||
let message = serde_json::from_str::<JSONRPCMessage>(&line)?;
|
||||
eprintln!("read message from stdout: {message:?}");
|
||||
Ok(message)
|
||||
@@ -1422,8 +1612,19 @@ impl McpProcess {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for McpProcess {
|
||||
impl Drop for AppServerTestProcess {
|
||||
fn drop(&mut self) {
|
||||
let AppServerBackend::Child(child) = &mut self.backend else {
|
||||
if let AppServerBackend::InProcessRunning { client, .. } = &mut self.backend
|
||||
&& let Some(client) = client.take()
|
||||
&& let Ok(handle) = tokio::runtime::Handle::try_current()
|
||||
{
|
||||
handle.spawn(async move {
|
||||
let _ = client.shutdown().await;
|
||||
});
|
||||
}
|
||||
return;
|
||||
};
|
||||
// These tests spawn a `codex-app-server` child process.
|
||||
//
|
||||
// We keep that child alive for the test and rely on Tokio's `kill_on_drop(true)` when this
|
||||
@@ -1440,24 +1641,24 @@ impl Drop for McpProcess {
|
||||
// 2. Poll briefly for graceful exit.
|
||||
// 3. If still alive, request termination with `start_kill()`.
|
||||
// 4. Poll `try_wait()` until the OS reports the child exited, with a short timeout.
|
||||
drop(self.stdin.take());
|
||||
drop(child.stdin.take());
|
||||
|
||||
let graceful_start = std::time::Instant::now();
|
||||
let graceful_timeout = std::time::Duration::from_millis(200);
|
||||
while graceful_start.elapsed() < graceful_timeout {
|
||||
match self.process.try_wait() {
|
||||
match child.process.try_wait() {
|
||||
Ok(Some(_)) => return,
|
||||
Ok(None) => std::thread::sleep(std::time::Duration::from_millis(5)),
|
||||
Err(_) => return,
|
||||
}
|
||||
}
|
||||
|
||||
let _ = self.process.start_kill();
|
||||
let _ = child.process.start_kill();
|
||||
|
||||
let start = std::time::Instant::now();
|
||||
let timeout = std::time::Duration::from_secs(5);
|
||||
while start.elapsed() < timeout {
|
||||
match self.process.try_wait() {
|
||||
match child.process.try_wait() {
|
||||
Ok(Some(_)) => return,
|
||||
Ok(None) => std::thread::sleep(std::time::Duration::from_millis(10)),
|
||||
Err(_) => return,
|
||||
@@ -1465,3 +1666,44 @@ impl Drop for McpProcess {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn build_in_process_start_args(
|
||||
codex_home: &Path,
|
||||
loader_overrides: &LoaderOverrides,
|
||||
initialize: InitializeParams,
|
||||
) -> anyhow::Result<in_process::InProcessStartArgs> {
|
||||
let codex_home = std::fs::canonicalize(codex_home)?;
|
||||
let config = ConfigBuilder::default()
|
||||
.codex_home(codex_home.clone())
|
||||
.fallback_cwd(Some(codex_home))
|
||||
.loader_overrides(loader_overrides.clone())
|
||||
.build()
|
||||
.await?;
|
||||
let state_db = codex_core::init_state_db(&config).await;
|
||||
Ok(in_process::InProcessStartArgs {
|
||||
arg0_paths: Arg0DispatchPaths::default(),
|
||||
config: Arc::new(config),
|
||||
cli_overrides: Vec::new(),
|
||||
loader_overrides: loader_overrides.clone(),
|
||||
cloud_requirements: CloudRequirementsLoader::default(),
|
||||
thread_config_loader: Arc::new(codex_config::NoopThreadConfigLoader),
|
||||
feedback: CodexFeedback::new(),
|
||||
log_db: None,
|
||||
state_db,
|
||||
environment_manager: Arc::new(EnvironmentManager::default_for_tests()),
|
||||
config_warnings: Vec::new(),
|
||||
session_source: SessionSource::Cli,
|
||||
enable_codex_api_key_env: false,
|
||||
plugin_startup_tasks: PluginStartupTasks::Skip,
|
||||
initialize,
|
||||
channel_capacity: in_process::DEFAULT_IN_PROCESS_CHANNEL_CAPACITY,
|
||||
})
|
||||
}
|
||||
|
||||
fn in_process_client(
|
||||
client: &Option<InProcessClientHandle>,
|
||||
) -> anyhow::Result<&InProcessClientHandle> {
|
||||
client
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow::format_err!("in-process app-server is closed"))
|
||||
}
|
||||
@@ -1,13 +1,16 @@
|
||||
mod analytics_server;
|
||||
mod app_server_test_process;
|
||||
mod auth_fixtures;
|
||||
mod config;
|
||||
mod mcp_process;
|
||||
mod mock_model_server;
|
||||
mod models_cache;
|
||||
mod responses;
|
||||
mod rollout;
|
||||
|
||||
pub use analytics_server::start_analytics_events_server;
|
||||
pub use app_server_test_process::AppServerTestProcess;
|
||||
pub use app_server_test_process::DEFAULT_CLIENT_NAME;
|
||||
pub use app_server_test_process::DISABLE_PLUGIN_STARTUP_TASKS_ARG;
|
||||
pub use auth_fixtures::ChatGptAuthFixture;
|
||||
pub use auth_fixtures::ChatGptIdTokenClaims;
|
||||
pub use auth_fixtures::encode_id_token;
|
||||
@@ -24,9 +27,6 @@ pub use core_test_support::test_absolute_path;
|
||||
pub use core_test_support::test_path_buf_with_windows;
|
||||
pub use core_test_support::test_tmp_path;
|
||||
pub use core_test_support::test_tmp_path_buf;
|
||||
pub use mcp_process::DEFAULT_CLIENT_NAME;
|
||||
pub use mcp_process::DISABLE_PLUGIN_STARTUP_TASKS_ARG;
|
||||
pub use mcp_process::McpProcess;
|
||||
pub use mock_model_server::create_mock_responses_server_repeating_assistant;
|
||||
pub use mock_model_server::create_mock_responses_server_sequence;
|
||||
pub use mock_model_server::create_mock_responses_server_sequence_unchecked;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
use chrono::Duration;
|
||||
@@ -92,7 +92,10 @@ shell_snapshot = false
|
||||
std::fs::write(config_toml, contents)
|
||||
}
|
||||
|
||||
async fn login_with_api_key_via_request(mcp: &mut McpProcess, api_key: &str) -> Result<()> {
|
||||
async fn login_with_api_key_via_request(
|
||||
mcp: &mut AppServerTestProcess,
|
||||
api_key: &str,
|
||||
) -> Result<()> {
|
||||
let request_id = mcp.send_login_account_api_key_request(api_key).await?;
|
||||
|
||||
let resp: JSONRPCResponse = timeout(
|
||||
@@ -110,7 +113,8 @@ async fn get_auth_status_no_auth() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path())?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -136,7 +140,7 @@ async fn get_auth_status_with_api_key() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
login_with_api_key_via_request(&mut mcp, "sk-test-key").await?;
|
||||
@@ -164,7 +168,7 @@ async fn get_auth_status_with_api_key_when_auth_not_required() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml_custom_provider(codex_home.path(), /*requires_openai_auth*/ false)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
login_with_api_key_via_request(&mut mcp, "sk-test-key").await?;
|
||||
@@ -197,7 +201,7 @@ async fn get_auth_status_with_api_key_no_include_token() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
login_with_api_key_via_request(&mut mcp, "sk-test-key").await?;
|
||||
@@ -225,7 +229,7 @@ async fn get_auth_status_with_api_key_refresh_requested() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
login_with_api_key_via_request(&mut mcp, "sk-test-key").await?;
|
||||
@@ -281,7 +285,7 @@ async fn get_auth_status_omits_token_after_permanent_refresh_failure() -> Result
|
||||
.await;
|
||||
|
||||
let refresh_url = format!("{}/oauth/token", server.uri());
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("OPENAI_API_KEY", None),
|
||||
@@ -363,7 +367,7 @@ async fn get_auth_status_omits_token_after_proactive_refresh_failure() -> Result
|
||||
.await;
|
||||
|
||||
let refresh_url = format!("{}/oauth/token", server.uri());
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("OPENAI_API_KEY", None),
|
||||
@@ -430,7 +434,7 @@ async fn get_auth_status_returns_token_after_proactive_refresh_recovery() -> Res
|
||||
.await;
|
||||
|
||||
let refresh_url = format!("{}/oauth/token", server.uri());
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("OPENAI_API_KEY", None),
|
||||
@@ -507,7 +511,7 @@ async fn login_api_key_rejected_when_forced_chatgpt() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml_forced_login(codex_home.path(), "chatgpt")?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_fake_rollout;
|
||||
use app_test_support::rollout_path;
|
||||
use app_test_support::to_response;
|
||||
@@ -93,7 +93,7 @@ async fn get_conversation_summary_by_thread_id_reads_rollout() -> Result<()> {
|
||||
))?,
|
||||
);
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -158,6 +158,7 @@ async fn get_conversation_summary_by_thread_id_reads_pathless_store_thread() ->
|
||||
config_warnings: Vec::new(),
|
||||
session_source: SessionSource::Cli,
|
||||
enable_codex_api_key_env: false,
|
||||
plugin_startup_tasks: codex_app_server::PluginStartupTasks::Start,
|
||||
initialize: InitializeParams {
|
||||
client_info: ClientInfo {
|
||||
name: "codex-app-server-tests".to_string(),
|
||||
@@ -210,7 +211,7 @@ async fn get_conversation_summary_by_relative_rollout_path_resolves_from_codex_h
|
||||
let relative_path = rollout_path.strip_prefix(codex_home.path())?.to_path_buf();
|
||||
let expected = expected_summary(thread_id, normalized_canonical_path(rollout_path)?);
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use anyhow::anyhow;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use codex_app_server_protocol::FuzzyFileSearchSessionCompletedNotification;
|
||||
use codex_app_server_protocol::FuzzyFileSearchSessionUpdatedNotification;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
@@ -44,15 +44,15 @@ shell_snapshot = false
|
||||
)
|
||||
}
|
||||
|
||||
async fn initialized_mcp(codex_home: &TempDir) -> Result<McpProcess> {
|
||||
async fn initialized_mcp(codex_home: &TempDir) -> Result<AppServerTestProcess> {
|
||||
create_config_toml(codex_home.path())?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
Ok(mcp)
|
||||
}
|
||||
|
||||
async fn wait_for_session_updated(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
session_id: &str,
|
||||
query: &str,
|
||||
file_expectation: FileExpectation,
|
||||
@@ -99,7 +99,7 @@ async fn wait_for_session_updated(
|
||||
}
|
||||
|
||||
async fn wait_for_session_completed(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
session_id: &str,
|
||||
) -> Result<FuzzyFileSearchSessionCompletedNotification> {
|
||||
let description = format!("session completion for sessionId={session_id}");
|
||||
@@ -140,7 +140,7 @@ async fn wait_for_session_completed(
|
||||
}
|
||||
|
||||
async fn assert_update_request_fails_for_missing_session(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
session_id: &str,
|
||||
query: &str,
|
||||
) -> Result<()> {
|
||||
@@ -161,7 +161,7 @@ async fn assert_update_request_fails_for_missing_session(
|
||||
}
|
||||
|
||||
async fn assert_no_session_updates_for(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
session_id: &str,
|
||||
grace_period: std::time::Duration,
|
||||
duration: std::time::Duration,
|
||||
@@ -236,7 +236,7 @@ async fn test_fuzzy_file_search_sorts_and_includes_indices() -> Result<()> {
|
||||
.to_string();
|
||||
|
||||
// Start MCP server and initialize.
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let root_path = root.path().to_string_lossy().to_string();
|
||||
@@ -302,7 +302,7 @@ async fn test_fuzzy_file_search_accepts_cancellation_token() -> Result<()> {
|
||||
|
||||
std::fs::write(root.path().join("alpha.txt"), "contents")?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let root_path = root.path().to_string_lossy().to_string();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use anyhow::bail;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::to_response;
|
||||
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
@@ -184,7 +184,8 @@ async fn logout_account_removes_auth_and_notifies() -> Result<()> {
|
||||
)?;
|
||||
assert!(codex_home.path().join("auth.json").exists());
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let id = mcp.send_logout_account_request().await?;
|
||||
@@ -251,7 +252,8 @@ async fn set_auth_token_updates_account_and_notifies() -> Result<()> {
|
||||
.chatgpt_account_id("org-embedded"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let set_id = mcp
|
||||
@@ -325,7 +327,8 @@ async fn account_read_refresh_token_is_noop_in_external_mode() -> Result<()> {
|
||||
.chatgpt_account_id("org-embedded"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let set_id = mcp
|
||||
@@ -384,7 +387,7 @@ async fn account_read_refresh_token_is_noop_in_external_mode() -> Result<()> {
|
||||
}
|
||||
|
||||
async fn respond_to_refresh_request(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
access_token: &str,
|
||||
chatgpt_account_id: &str,
|
||||
chatgpt_plan_type: Option<&str>,
|
||||
@@ -450,7 +453,8 @@ async fn external_auth_refreshes_on_unauthorized() -> Result<()> {
|
||||
.chatgpt_account_id("org-refreshed"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let set_id = mcp
|
||||
@@ -556,7 +560,8 @@ async fn external_auth_refresh_error_fails_turn() -> Result<()> {
|
||||
.chatgpt_account_id("org-initial"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let set_id = mcp
|
||||
@@ -678,7 +683,8 @@ async fn external_auth_refresh_mismatched_workspace_fails_turn() -> Result<()> {
|
||||
.chatgpt_account_id("org-other"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let set_id = mcp
|
||||
@@ -793,7 +799,8 @@ async fn external_auth_refresh_invalid_access_token_fails_turn() -> Result<()> {
|
||||
.chatgpt_account_id("org-initial"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let set_id = mcp
|
||||
@@ -885,7 +892,7 @@ async fn login_account_api_key_succeeds_and_notifies() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), CreateConfigTomlParams::default())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let req_id = mcp
|
||||
@@ -939,7 +946,7 @@ async fn login_account_api_key_rejected_when_forced_chatgpt() -> Result<()> {
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -969,7 +976,7 @@ async fn login_account_chatgpt_rejected_when_forced_api() -> Result<()> {
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp.send_login_account_chatgpt_request().await?;
|
||||
@@ -1002,7 +1009,7 @@ async fn login_account_chatgpt_device_code_returns_error_when_disabled() -> Resu
|
||||
mock_device_code_usercode_failure(&mock_server, /*status*/ 404).await;
|
||||
|
||||
let issuer = mock_server.uri();
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("OPENAI_API_KEY", None),
|
||||
@@ -1067,7 +1074,7 @@ async fn login_account_chatgpt_device_code_succeeds_and_notifies() -> Result<()>
|
||||
mock_device_code_oauth_token(&mock_server, &id_token).await;
|
||||
|
||||
let issuer = mock_server.uri();
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("OPENAI_API_KEY", None),
|
||||
@@ -1144,7 +1151,7 @@ async fn login_account_chatgpt_device_code_failure_notifies_without_account_upda
|
||||
mock_device_code_token_failure(&mock_server, /*status*/ 500).await;
|
||||
|
||||
let issuer = mock_server.uri();
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("OPENAI_API_KEY", None),
|
||||
@@ -1219,7 +1226,7 @@ async fn login_account_chatgpt_device_code_can_be_cancelled() -> Result<()> {
|
||||
mock_device_code_token_failure(&mock_server, /*status*/ 404).await;
|
||||
|
||||
let issuer = mock_server.uri();
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("OPENAI_API_KEY", None),
|
||||
@@ -1292,7 +1299,7 @@ async fn login_account_chatgpt_start_can_be_cancelled() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), CreateConfigTomlParams::default())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp.send_login_account_chatgpt_request().await?;
|
||||
@@ -1358,7 +1365,7 @@ async fn set_auth_token_cancels_active_chatgpt_login() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), CreateConfigTomlParams::default())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
// Initiate the ChatGPT login flow
|
||||
@@ -1433,7 +1440,7 @@ async fn login_account_chatgpt_includes_forced_workspace_query_param() -> Result
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp.send_login_account_chatgpt_request().await?;
|
||||
@@ -1465,7 +1472,8 @@ async fn get_account_no_auth() -> Result<()> {
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let params = GetAccountParams {
|
||||
@@ -1496,7 +1504,7 @@ async fn get_account_with_api_key() -> Result<()> {
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let req_id = mcp
|
||||
@@ -1540,7 +1548,7 @@ async fn get_account_when_auth_not_required() -> Result<()> {
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let params = GetAccountParams {
|
||||
@@ -1581,7 +1589,7 @@ region = "us-west-2"
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let params = GetAccountParams {
|
||||
@@ -1622,7 +1630,8 @@ async fn get_account_with_chatgpt() -> Result<()> {
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let params = GetAccountParams {
|
||||
@@ -1682,7 +1691,7 @@ async fn get_account_omits_chatgpt_after_permanent_refresh_failure() -> Result<(
|
||||
.await;
|
||||
|
||||
let refresh_url = format!("{}/oauth/token", server.uri());
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("OPENAI_API_KEY", None),
|
||||
@@ -1748,7 +1757,8 @@ async fn get_account_with_chatgpt_missing_plan_claim_returns_unknown() -> Result
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let params = GetAccountParams {
|
||||
|
||||
@@ -7,8 +7,8 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::bail;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
use axum::Json;
|
||||
@@ -63,7 +63,7 @@ const DEFAULT_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
#[tokio::test]
|
||||
async fn list_apps_returns_empty_when_connectors_disabled() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
@@ -124,7 +124,7 @@ async fn list_apps_returns_empty_with_api_key_auth() -> Result<()> {
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -186,7 +186,7 @@ async fn list_apps_returns_empty_when_workspace_codex_plugins_disabled() -> Resu
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -245,7 +245,7 @@ async fn list_apps_uses_thread_feature_flag_when_thread_id_is_provided() -> Resu
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_request = mcp
|
||||
@@ -361,7 +361,7 @@ enabled = false
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -480,7 +480,7 @@ async fn list_apps_emits_updates_and_returns_after_both_lists_load() -> Result<(
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -620,7 +620,7 @@ async fn list_apps_waits_for_accessible_data_before_emitting_directory_updates()
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -726,7 +726,7 @@ async fn list_apps_does_not_emit_empty_interim_updates() -> Result<()> {
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -835,7 +835,7 @@ async fn list_apps_paginates_results() -> Result<()> {
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let first_request = mcp
|
||||
@@ -955,7 +955,7 @@ async fn list_apps_force_refetch_preserves_previous_cache_on_failure() -> Result
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let initial_request = mcp
|
||||
@@ -1081,7 +1081,7 @@ async fn list_apps_force_refetch_patches_updates_from_cached_snapshots() -> Resu
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let warm_request = mcp
|
||||
@@ -1304,7 +1304,7 @@ async fn experimental_feature_enablement_set_refreshes_apps_list_when_apps_turn_
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let disable_request = mcp
|
||||
@@ -1371,7 +1371,7 @@ async fn experimental_feature_enablement_set_refreshes_apps_list_when_apps_turn_
|
||||
}
|
||||
|
||||
async fn read_app_list_updated_notification(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
) -> Result<AppListUpdatedNotification> {
|
||||
let notification = timeout(
|
||||
DEFAULT_TIMEOUT,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use anyhow::Result;
|
||||
use anyhow::bail;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
use codex_app_server_protocol::AttestationGenerateResponse;
|
||||
@@ -76,7 +76,8 @@ async fn attestation_generate_round_trip_adds_header_to_responses_websocket_hand
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let initialized = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.initialize_with_capabilities(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
@@ -44,7 +44,7 @@ async fn turn_start_forwards_client_metadata_to_responses_request_v2() -> Result
|
||||
/*supports_websockets*/ false,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -126,7 +126,7 @@ async fn turn_steer_updates_client_metadata_on_follow_up_responses_request_v2()
|
||||
/*supports_websockets*/ false,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -248,7 +248,7 @@ async fn turn_start_forwards_client_metadata_to_responses_websocket_request_body
|
||||
/*supports_websockets*/ true,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::CollaborationModeListParams;
|
||||
use codex_app_server_protocol::CollaborationModeListResponse;
|
||||
@@ -28,7 +28,7 @@ const DEFAULT_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
#[tokio::test]
|
||||
async fn list_collaboration_modes_returns_presets() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
use app_test_support::to_response;
|
||||
use base64::Engine;
|
||||
@@ -46,7 +46,7 @@ async fn command_exec_without_streams_can_be_terminated() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let process_id = "sleep-1".to_string();
|
||||
@@ -96,7 +96,7 @@ async fn command_exec_without_process_id_keeps_buffered_compatibility() -> Resul
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let command_request_id = mcp
|
||||
@@ -144,7 +144,7 @@ async fn command_exec_env_overrides_merge_with_server_environment_and_support_un
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[("COMMAND_EXEC_BASELINE", Some("server"))],
|
||||
)
|
||||
@@ -202,7 +202,7 @@ async fn command_exec_accepts_permission_profile() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let command_request_id = mcp
|
||||
@@ -252,7 +252,7 @@ async fn command_exec_permission_profile_project_roots_use_command_cwd() -> Resu
|
||||
let command_dir = codex_home.path().join("command-cwd");
|
||||
std::fs::create_dir(&command_dir)?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let mut permission_profile = root_read_only_permission_profile();
|
||||
@@ -317,7 +317,7 @@ async fn command_exec_rejects_sandbox_policy_with_permission_profile() -> Result
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let command_request_id = mcp
|
||||
@@ -355,7 +355,7 @@ async fn command_exec_rejects_disable_timeout_with_timeout_ms() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let command_request_id = mcp
|
||||
@@ -393,7 +393,7 @@ async fn command_exec_rejects_disable_output_cap_with_output_bytes_cap() -> Resu
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let command_request_id = mcp
|
||||
@@ -431,7 +431,7 @@ async fn command_exec_rejects_negative_timeout_ms() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let command_request_id = mcp
|
||||
@@ -469,7 +469,7 @@ async fn command_exec_without_process_id_rejects_streaming() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let command_request_id = mcp
|
||||
@@ -507,7 +507,7 @@ async fn command_exec_non_streaming_respects_output_cap() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let command_request_id = mcp
|
||||
@@ -554,7 +554,7 @@ async fn command_exec_streaming_does_not_buffer_output() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let process_id = "stream-cap-1".to_string();
|
||||
@@ -618,7 +618,7 @@ async fn command_exec_pipe_streams_output_and_accepts_write() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let process_id = "pipe-1".to_string();
|
||||
@@ -694,7 +694,7 @@ async fn command_exec_tty_implies_streaming_and_reports_pty_output() -> Result<(
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let process_id = "tty-1".to_string();
|
||||
@@ -765,7 +765,7 @@ async fn command_exec_tty_supports_initial_size_and_resize() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let process_id = "tty-size-1".to_string();
|
||||
@@ -934,7 +934,7 @@ async fn command_exec_process_ids_are_connection_scoped_and_disconnect_terminate
|
||||
}
|
||||
|
||||
async fn read_command_exec_delta(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
) -> Result<CommandExecOutputDeltaNotification> {
|
||||
let notification = mcp
|
||||
.read_stream_until_notification_message("command/exec/outputDelta")
|
||||
@@ -943,7 +943,7 @@ async fn read_command_exec_delta(
|
||||
}
|
||||
|
||||
async fn wait_for_command_exec_output_contains(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
process_id: &str,
|
||||
stream: CommandExecOutputStream,
|
||||
expected: &str,
|
||||
@@ -966,7 +966,7 @@ async fn wait_for_command_exec_output_contains(
|
||||
}
|
||||
|
||||
async fn wait_for_command_exec_outputs_contains(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
process_id: &str,
|
||||
stdout_expected: &str,
|
||||
stderr_expected: &str,
|
||||
@@ -984,7 +984,7 @@ async fn wait_for_command_exec_outputs_contains(
|
||||
}
|
||||
|
||||
enum CommandExecDeltaReader<'a> {
|
||||
Mcp(&'a mut McpProcess),
|
||||
Mcp(&'a mut AppServerTestProcess),
|
||||
Websocket(&'a mut super::connection_handling_websocket::WsClient),
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#![expect(clippy::expect_used)]
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
use app_test_support::write_mock_responses_config_toml;
|
||||
@@ -82,7 +82,7 @@ async fn auto_compaction_local_emits_started_and_completed_items() -> Result<()>
|
||||
COMPACT_PROMPT,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_id = start_thread(&mut mcp).await?;
|
||||
@@ -162,7 +162,8 @@ async fn auto_compaction_remote_emits_started_and_completed_items() -> Result<()
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_id = start_thread(&mut mcp).await?;
|
||||
@@ -216,7 +217,7 @@ async fn thread_compact_start_triggers_compaction_and_returns_empty_response() -
|
||||
COMPACT_PROMPT,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_id = start_thread(&mut mcp).await?;
|
||||
@@ -266,7 +267,7 @@ async fn thread_compact_start_rejects_invalid_thread_id() -> Result<()> {
|
||||
COMPACT_PROMPT,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -302,7 +303,7 @@ async fn thread_compact_start_rejects_unknown_thread_id() -> Result<()> {
|
||||
COMPACT_PROMPT,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -322,7 +323,7 @@ async fn thread_compact_start_rejects_unknown_thread_id() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn start_thread(mcp: &mut McpProcess) -> Result<String> {
|
||||
async fn start_thread(mcp: &mut AppServerTestProcess) -> Result<String> {
|
||||
let thread_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
@@ -338,7 +339,11 @@ async fn start_thread(mcp: &mut McpProcess) -> Result<String> {
|
||||
Ok(thread.id)
|
||||
}
|
||||
|
||||
async fn send_turn_and_wait(mcp: &mut McpProcess, thread_id: &str, text: &str) -> Result<String> {
|
||||
async fn send_turn_and_wait(
|
||||
mcp: &mut AppServerTestProcess,
|
||||
thread_id: &str,
|
||||
text: &str,
|
||||
) -> Result<String> {
|
||||
let turn_id = mcp
|
||||
.send_turn_start_request(TurnStartParams {
|
||||
thread_id: thread_id.to_string(),
|
||||
@@ -359,7 +364,7 @@ async fn send_turn_and_wait(mcp: &mut McpProcess, thread_id: &str, text: &str) -
|
||||
Ok(turn.id)
|
||||
}
|
||||
|
||||
async fn wait_for_turn_completed(mcp: &mut McpProcess, turn_id: &str) -> Result<()> {
|
||||
async fn wait_for_turn_completed(mcp: &mut AppServerTestProcess, turn_id: &str) -> Result<()> {
|
||||
loop {
|
||||
let notification: JSONRPCNotification = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
@@ -375,7 +380,7 @@ async fn wait_for_turn_completed(mcp: &mut McpProcess, turn_id: &str) -> Result<
|
||||
}
|
||||
|
||||
async fn wait_for_context_compaction_started(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
) -> Result<ItemStartedNotification> {
|
||||
loop {
|
||||
let notification: JSONRPCNotification = timeout(
|
||||
@@ -392,7 +397,7 @@ async fn wait_for_context_compaction_started(
|
||||
}
|
||||
|
||||
async fn wait_for_context_compaction_completed(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
) -> Result<ItemCompletedNotification> {
|
||||
loop {
|
||||
let notification: JSONRPCNotification = timeout(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::test_path_buf_with_windows;
|
||||
use app_test_support::test_tmp_path_buf;
|
||||
use app_test_support::to_response;
|
||||
@@ -57,7 +57,7 @@ sandbox_mode = "workspace-write"
|
||||
let codex_home_path = codex_home.path().canonicalize()?;
|
||||
let user_file = AbsolutePathBuf::try_from(codex_home_path.join("config.toml"))?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -109,7 +109,7 @@ view_image = false
|
||||
let codex_home_path = codex_home.path().canonicalize()?;
|
||||
let user_file = AbsolutePathBuf::try_from(codex_home_path.join("config.toml"))?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -187,7 +187,7 @@ location = { country = "US", city = "New York", timezone = "America/New_York" }
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -231,7 +231,7 @@ web_search = true
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -267,7 +267,7 @@ default_tools_approval_mode = "prompt"
|
||||
let codex_home_path = codex_home.path().canonicalize()?;
|
||||
let user_file = AbsolutePathBuf::try_from(codex_home_path.join("config.toml"))?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -352,7 +352,7 @@ model_reasoning_effort = "high"
|
||||
set_project_trust_level(codex_home.path(), workspace.path(), TrustLevel::Trusted)?;
|
||||
let project_config = AbsolutePathBuf::try_from(project_config_dir)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -422,7 +422,7 @@ writable_roots = [{}]
|
||||
|
||||
let managed_path_str = managed_path.display().to_string();
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[(
|
||||
"CODEX_APP_SERVER_MANAGED_CONFIG_PATH",
|
||||
@@ -516,7 +516,7 @@ model = "gpt-old"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let read_id = mcp
|
||||
@@ -582,7 +582,7 @@ model = "gpt-old"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let write_id = mcp
|
||||
@@ -630,7 +630,7 @@ model = "gpt-old"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let write_id = mcp
|
||||
@@ -665,7 +665,7 @@ async fn config_batch_write_applies_multiple_edits() -> Result<()> {
|
||||
let codex_home = tmp_dir.path().canonicalize()?;
|
||||
write_config(&tmp_dir, "")?;
|
||||
|
||||
let mut mcp = McpProcess::new(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let writable_root = test_tmp_path_buf();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
use app_test_support::to_response;
|
||||
@@ -51,7 +51,7 @@ async fn thread_start_injects_dynamic_tools_into_model_requests() -> Result<()>
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
// Use a minimal JSON schema so we can assert the tool payload round-trips.
|
||||
@@ -134,7 +134,7 @@ async fn thread_start_keeps_hidden_dynamic_tools_out_of_model_requests() -> Resu
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let dynamic_tool = DynamicToolSpec {
|
||||
@@ -206,7 +206,7 @@ async fn thread_start_rejects_hidden_dynamic_tools_without_namespace() -> Result
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let dynamic_tool = DynamicToolSpec {
|
||||
@@ -246,7 +246,7 @@ async fn thread_start_rejects_dynamic_tools_not_supported_by_responses() -> Resu
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let dynamic_tool = DynamicToolSpec {
|
||||
@@ -311,7 +311,7 @@ async fn dynamic_tool_call_round_trip_sends_text_content_items_to_model() -> Res
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let dynamic_tool = DynamicToolSpec {
|
||||
@@ -486,7 +486,7 @@ async fn dynamic_tool_call_round_trip_sends_content_items_to_model() -> Result<(
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let dynamic_tool = DynamicToolSpec {
|
||||
@@ -704,7 +704,7 @@ fn function_call_output_raw_output(body: &Value, call_id: &str) -> Option<Value>
|
||||
}
|
||||
|
||||
async fn wait_for_dynamic_tool_started(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
call_id: &str,
|
||||
) -> Result<ItemStartedNotification> {
|
||||
loop {
|
||||
@@ -724,7 +724,7 @@ async fn wait_for_dynamic_tool_started(
|
||||
}
|
||||
|
||||
async fn wait_for_dynamic_tool_completed(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
call_id: &str,
|
||||
) -> Result<ItemCompletedNotification> {
|
||||
loop {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::DEFAULT_CLIENT_NAME;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::AskForApproval;
|
||||
@@ -29,7 +29,7 @@ const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
#[tokio::test]
|
||||
async fn mock_experimental_method_requires_experimental_api_capability() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
|
||||
let init = mcp
|
||||
.initialize_with_capabilities(
|
||||
@@ -60,7 +60,7 @@ async fn mock_experimental_method_requires_experimental_api_capability() -> Resu
|
||||
#[tokio::test]
|
||||
async fn realtime_conversation_start_requires_experimental_api_capability() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
|
||||
let init = mcp
|
||||
.initialize_with_capabilities(
|
||||
@@ -98,7 +98,7 @@ async fn realtime_conversation_start_requires_experimental_api_capability() -> R
|
||||
#[tokio::test]
|
||||
async fn thread_memory_mode_set_requires_experimental_api_capability() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
|
||||
let init = mcp
|
||||
.initialize_with_capabilities(
|
||||
@@ -132,7 +132,7 @@ async fn thread_memory_mode_set_requires_experimental_api_capability() -> Result
|
||||
#[tokio::test]
|
||||
async fn realtime_webrtc_start_requires_experimental_api_capability() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
|
||||
let init = mcp
|
||||
.initialize_with_capabilities(
|
||||
@@ -175,7 +175,7 @@ async fn thread_start_mock_field_requires_experimental_api_capability() -> Resul
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
let init = mcp
|
||||
.initialize_with_capabilities(
|
||||
default_client_info(),
|
||||
@@ -213,7 +213,7 @@ async fn thread_start_without_dynamic_tools_allows_without_experimental_api_capa
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
let init = mcp
|
||||
.initialize_with_capabilities(
|
||||
default_client_info(),
|
||||
@@ -250,7 +250,7 @@ async fn thread_start_granular_approval_policy_requires_experimental_api_capabil
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
let init = mcp
|
||||
.initialize_with_capabilities(
|
||||
default_client_info(),
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
use codex_app_server_protocol::ConfigReadParams;
|
||||
@@ -47,7 +47,7 @@ async fn experimental_feature_list_returns_feature_metadata_with_stage() -> Resu
|
||||
))
|
||||
.build()
|
||||
.await?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
@@ -131,7 +131,7 @@ async fn experimental_feature_list_marks_apps_and_plugins_disabled_by_workspace_
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -163,7 +163,7 @@ async fn experimental_feature_enablement_set_applies_to_global_and_thread_config
|
||||
let project_cwd = codex_home.path().join("project");
|
||||
std::fs::create_dir_all(&project_cwd)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let actual =
|
||||
@@ -198,7 +198,7 @@ async fn experimental_feature_enablement_set_does_not_override_user_config() ->
|
||||
codex_home.path().join("config.toml"),
|
||||
"[features]\nmemories = false\n",
|
||||
)?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let actual = set_experimental_feature_enablement(
|
||||
@@ -229,7 +229,7 @@ async fn experimental_feature_enablement_set_does_not_override_user_config() ->
|
||||
#[tokio::test]
|
||||
async fn experimental_feature_enablement_set_only_updates_named_features() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
set_experimental_feature_enablement(&mut mcp, BTreeMap::from([("apps".to_string(), true)]))
|
||||
@@ -310,7 +310,7 @@ async fn experimental_feature_enablement_set_only_updates_named_features() -> Re
|
||||
#[tokio::test]
|
||||
async fn experimental_feature_enablement_set_allows_remote_control() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
let remote_control_enabled = false;
|
||||
let enablement = BTreeMap::from([("remote_control".to_string(), remote_control_enabled)]);
|
||||
@@ -328,7 +328,7 @@ async fn experimental_feature_enablement_set_allows_remote_control() -> Result<(
|
||||
#[tokio::test]
|
||||
async fn experimental_feature_enablement_set_empty_map_is_no_op() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
set_experimental_feature_enablement(&mut mcp, BTreeMap::from([("apps".to_string(), true)]))
|
||||
@@ -358,7 +358,7 @@ async fn experimental_feature_enablement_set_empty_map_is_no_op() -> Result<()>
|
||||
#[tokio::test]
|
||||
async fn experimental_feature_enablement_set_rejects_non_allowlisted_feature() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -392,7 +392,7 @@ async fn experimental_feature_enablement_set_rejects_non_allowlisted_feature() -
|
||||
}
|
||||
|
||||
async fn set_experimental_feature_enablement(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
enablement: BTreeMap<String, bool>,
|
||||
) -> Result<ExperimentalFeatureEnablementSetResponse> {
|
||||
let request_id = mcp
|
||||
@@ -403,7 +403,10 @@ async fn set_experimental_feature_enablement(
|
||||
read_response(mcp, request_id).await
|
||||
}
|
||||
|
||||
async fn read_config(mcp: &mut McpProcess, cwd: Option<String>) -> Result<ConfigReadResponse> {
|
||||
async fn read_config(
|
||||
mcp: &mut AppServerTestProcess,
|
||||
cwd: Option<String>,
|
||||
) -> Result<ConfigReadResponse> {
|
||||
let request_id = mcp
|
||||
.send_config_read_request(ConfigReadParams {
|
||||
include_layers: false,
|
||||
@@ -413,7 +416,10 @@ async fn read_config(mcp: &mut McpProcess, cwd: Option<String>) -> Result<Config
|
||||
read_response(mcp, request_id).await
|
||||
}
|
||||
|
||||
async fn read_response<T: DeserializeOwned>(mcp: &mut McpProcess, request_id: i64) -> Result<T> {
|
||||
async fn read_response<T: DeserializeOwned>(
|
||||
mcp: &mut AppServerTestProcess,
|
||||
request_id: i64,
|
||||
) -> Result<T> {
|
||||
let response: JSONRPCResponse = timeout(
|
||||
DEFAULT_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(request_id)),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_mock_responses_server_repeating_assistant;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_mock_responses_config_toml;
|
||||
@@ -38,7 +38,8 @@ async fn external_agent_config_import_sends_completion_notification_for_sync_onl
|
||||
let codex_home = TempDir::new()?;
|
||||
let home_dir = codex_home.path().display().to_string();
|
||||
let mut mcp =
|
||||
McpProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))]).await?;
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))])
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -117,7 +118,8 @@ async fn external_agent_config_import_sends_completion_notification_for_local_pl
|
||||
|
||||
let home_dir = codex_home.path().display().to_string();
|
||||
let mut mcp =
|
||||
McpProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))]).await?;
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))])
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -205,7 +207,8 @@ async fn external_agent_config_import_sends_completion_notification_after_pendin
|
||||
|
||||
let home_dir = codex_home.path().display().to_string();
|
||||
let mut mcp =
|
||||
McpProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))]).await?;
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))])
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -283,7 +286,8 @@ async fn external_agent_config_import_creates_session_rollouts() -> Result<()> {
|
||||
|
||||
let home_dir = codex_home.path().display().to_string();
|
||||
let mut mcp =
|
||||
McpProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))]).await?;
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))])
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -455,7 +459,8 @@ async fn external_agent_config_import_accepts_detected_session_payload_after_res
|
||||
|
||||
let home_dir = codex_home.path().display().to_string();
|
||||
let mut mcp =
|
||||
McpProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))]).await?;
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))])
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -540,7 +545,8 @@ async fn external_agent_config_import_skips_already_imported_session_versions()
|
||||
|
||||
let home_dir = codex_home.path().display().to_string();
|
||||
let mut mcp =
|
||||
McpProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))]).await?;
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))])
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -636,7 +642,8 @@ async fn external_agent_config_import_returns_before_background_session_import_f
|
||||
|
||||
let home_dir = codex_home.path().display().to_string();
|
||||
let mut mcp =
|
||||
McpProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))]).await?;
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))])
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -765,7 +772,8 @@ async fn external_agent_config_import_rejects_undetected_session_paths() -> Resu
|
||||
|
||||
let home_dir = codex_home.path().display().to_string();
|
||||
let mut mcp =
|
||||
McpProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))]).await?;
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))])
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -884,7 +892,8 @@ async fn external_agent_config_import_compacts_huge_session_before_first_follow_
|
||||
|
||||
let home_dir = codex_home.path().display().to_string();
|
||||
let mut mcp =
|
||||
McpProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))]).await?;
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("HOME", Some(home_dir.as_str()))])
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::to_response;
|
||||
use base64::Engine;
|
||||
use base64::engine::general_purpose::STANDARD;
|
||||
@@ -35,14 +35,14 @@ const DEFAULT_READ_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
const DEFAULT_READ_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
const OPTIONAL_FS_CHANGE_TIMEOUT: Duration = Duration::from_secs(2);
|
||||
|
||||
async fn initialized_mcp(codex_home: &TempDir) -> Result<McpProcess> {
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
async fn initialized_mcp(codex_home: &TempDir) -> Result<AppServerTestProcess> {
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
Ok(mcp)
|
||||
}
|
||||
|
||||
async fn expect_error_message(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
request_id: i64,
|
||||
expected_message: &str,
|
||||
) -> Result<()> {
|
||||
@@ -830,7 +830,7 @@ fn fs_changed_notification(notification: JSONRPCNotification) -> Result<FsChange
|
||||
}
|
||||
|
||||
async fn maybe_fs_changed_notification(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
) -> Result<Option<FsChangedNotification>> {
|
||||
match timeout(
|
||||
OPTIONAL_FS_CHANGE_TIMEOUT,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
use app_test_support::to_response;
|
||||
@@ -113,7 +113,7 @@ async fn hooks_list_shows_discovered_hook() -> Result<()> {
|
||||
let cwd = TempDir::new()?;
|
||||
write_user_hook_config(codex_home.path())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -189,7 +189,7 @@ async fn hooks_list_shows_discovered_plugin_hook() -> Result<()> {
|
||||
}"#,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -248,7 +248,7 @@ async fn hooks_list_shows_plugin_hook_load_warnings() -> Result<()> {
|
||||
let cwd = TempDir::new()?;
|
||||
write_plugin_hook_config(codex_home.path(), "{ not-json")?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -304,7 +304,7 @@ timeout = 5
|
||||
)?;
|
||||
set_project_trust_level(codex_home.path(), workspace.path(), TrustLevel::Trusted)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -374,7 +374,7 @@ async fn config_batch_write_toggles_user_hook() -> Result<()> {
|
||||
let cwd = TempDir::new()?;
|
||||
write_user_hook_config(codex_home.path())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -525,7 +525,7 @@ command = "python3 {hook_script_path}"
|
||||
),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let hook_list_id = mcp
|
||||
@@ -772,7 +772,7 @@ command = "python3 {hook_script_path}"
|
||||
),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let hook_list_id = mcp
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
use app_test_support::to_response;
|
||||
@@ -33,7 +33,7 @@ async fn initialize_uses_client_info_name_as_originator() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let expected_codex_home = AbsolutePathBuf::try_from(codex_home.path().canonicalize()?)?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
|
||||
let message = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
@@ -68,7 +68,7 @@ async fn initialize_probe_does_not_override_originator() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(responses).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
|
||||
let message = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
@@ -96,7 +96,7 @@ async fn initialize_respects_originator_override_env_var() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let expected_codex_home = AbsolutePathBuf::try_from(codex_home.path().canonicalize()?)?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[(
|
||||
"CODEX_INTERNAL_ORIGINATOR_OVERRIDE",
|
||||
@@ -138,7 +138,7 @@ async fn initialize_rejects_invalid_client_name() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(responses).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[("CODEX_INTERNAL_ORIGINATOR_OVERRIDE", None)],
|
||||
)
|
||||
@@ -173,7 +173,7 @@ async fn initialize_opt_out_notification_methods_filters_notifications() -> Resu
|
||||
let server = create_mock_responses_server_sequence_unchecked(responses).await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
|
||||
let message = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
@@ -255,7 +255,7 @@ async fn turn_start_notify_payload_includes_initialize_client_name() -> Result<(
|
||||
),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.initialize_with_client_info(ClientInfo {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_app_server_protocol::MarketplaceAddParams;
|
||||
@@ -28,7 +28,7 @@ async fn marketplace_add_local_directory_source() -> Result<()> {
|
||||
r#"{"name":"sample"}"#,
|
||||
)?;
|
||||
std::fs::write(source.join("plugins/sample/marker.txt"), "local ref")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_app_server_protocol::MarketplaceRemoveParams;
|
||||
@@ -53,7 +53,7 @@ async fn marketplace_remove_deletes_config_and_installed_root() -> Result<()> {
|
||||
write_installed_marketplace(codex_home.path(), "debug")?;
|
||||
let installed_root = marketplace_install_root(codex_home.path()).join("debug");
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -91,7 +91,7 @@ async fn marketplace_remove_deletes_config_and_installed_root() -> Result<()> {
|
||||
async fn marketplace_remove_rejects_unknown_marketplace() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_app_server_protocol::MarketplaceUpgradeParams;
|
||||
@@ -127,7 +127,7 @@ fn expected_installed_root(codex_home: &Path, marketplace_name: &str) -> Result<
|
||||
}
|
||||
|
||||
async fn send_marketplace_upgrade(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
marketplace_name: Option<&str>,
|
||||
) -> Result<MarketplaceUpgradeResponse> {
|
||||
let request_id = mcp
|
||||
@@ -169,7 +169,7 @@ async fn marketplace_upgrade_all_configured_git_marketplaces() -> Result<()> {
|
||||
)?;
|
||||
disable_plugin_startup_tasks(codex_home.path())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let debug_root = expected_installed_root(codex_home.path(), "debug")?;
|
||||
@@ -223,7 +223,7 @@ async fn marketplace_upgrade_named_marketplace_only() -> Result<()> {
|
||||
)?;
|
||||
disable_plugin_startup_tasks(codex_home.path())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let tools_root = expected_installed_root(codex_home.path(), "tools")?;
|
||||
@@ -264,7 +264,7 @@ async fn marketplace_upgrade_returns_empty_roots_when_already_up_to_date() -> Re
|
||||
)?;
|
||||
disable_plugin_startup_tasks(codex_home.path())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
let first_response = send_marketplace_upgrade(&mut mcp, Some("debug")).await?;
|
||||
assert!(first_response.errors.is_empty());
|
||||
@@ -292,7 +292,7 @@ async fn marketplace_upgrade_rejects_unknown_or_non_git_marketplace() -> Result<
|
||||
&configured_local_marketplace_update(&local_source.path().display().to_string()),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
for marketplace_name in ["missing", "local-only"] {
|
||||
|
||||
@@ -2,8 +2,8 @@ use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
use axum::Router;
|
||||
@@ -92,7 +92,7 @@ stream_max_retries = 0
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_start_id = mcp
|
||||
@@ -157,7 +157,7 @@ apps = true
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let read_request_id = mcp
|
||||
@@ -209,6 +209,7 @@ async fn mcp_resource_read_returns_error_for_unknown_thread() -> Result<()> {
|
||||
config_warnings: Vec::new(),
|
||||
session_source: SessionSource::Cli,
|
||||
enable_codex_api_key_env: false,
|
||||
plugin_startup_tasks: codex_app_server::PluginStartupTasks::Start,
|
||||
initialize: InitializeParams {
|
||||
client_info: ClientInfo {
|
||||
name: "codex-app-server-tests".to_string(),
|
||||
|
||||
@@ -2,8 +2,8 @@ use std::borrow::Cow;
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
use axum::Json;
|
||||
@@ -116,7 +116,7 @@ async fn mcp_server_elicitation_round_trip() -> Result<()> {
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_start_id = mcp
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_mock_responses_config_toml;
|
||||
@@ -62,7 +62,7 @@ url = "{mcp_server_url}/mcp"
|
||||
));
|
||||
std::fs::write(config_path, config_toml)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -233,7 +233,7 @@ url = "{mcp_server_url}/mcp"
|
||||
));
|
||||
std::fs::write(config_path, config_toml)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -297,7 +297,7 @@ url = "{underscore_server_url}/mcp"
|
||||
));
|
||||
std::fs::write(config_path, config_toml)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
use app_test_support::create_mock_responses_server_sequence;
|
||||
use app_test_support::to_response;
|
||||
@@ -94,7 +94,7 @@ url = "{mcp_server_url}/mcp"
|
||||
));
|
||||
std::fs::write(config_path, config_toml)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_start_id = mcp
|
||||
@@ -161,7 +161,7 @@ url = "{mcp_server_url}/mcp"
|
||||
#[tokio::test]
|
||||
async fn mcp_server_tool_call_returns_error_for_unknown_thread() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -212,7 +212,7 @@ url = "{mcp_server_url}/mcp"
|
||||
));
|
||||
std::fs::write(config_path, config_toml)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_start_id = mcp
|
||||
@@ -322,7 +322,7 @@ url = "{mcp_server_url}/mcp"
|
||||
));
|
||||
std::fs::write(config_path, config_toml)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_start_id = mcp
|
||||
@@ -442,7 +442,7 @@ url = "{mcp_server_url}/mcp"
|
||||
));
|
||||
std::fs::write(config_path, config_toml)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_start_id = mcp
|
||||
@@ -684,7 +684,7 @@ async fn start_mcp_server() -> Result<(String, JoinHandle<()>)> {
|
||||
}
|
||||
|
||||
async fn wait_for_mcp_tool_call_completed(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
call_id: &str,
|
||||
) -> Result<ItemCompletedNotification> {
|
||||
loop {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::to_response;
|
||||
use chrono::Utc;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
@@ -36,7 +36,7 @@ async fn memory_reset_clears_memory_files_and_rows_preserves_threads() -> Result
|
||||
|
||||
let thread_id = seed_stage1_output(&state_db, codex_home.path()).await?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_models_cache;
|
||||
use codex_app_server_protocol::JSONRPCError;
|
||||
@@ -86,7 +86,7 @@ fn expected_visible_models() -> Vec<Model> {
|
||||
async fn list_models_returns_all_models_with_large_limit() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
@@ -120,7 +120,7 @@ async fn list_models_returns_all_models_with_large_limit() -> Result<()> {
|
||||
async fn list_models_includes_hidden_models() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
@@ -152,7 +152,7 @@ async fn list_models_includes_hidden_models() -> Result<()> {
|
||||
async fn list_models_pagination_works() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
@@ -201,7 +201,7 @@ async fn list_models_pagination_works() -> Result<()> {
|
||||
async fn list_models_rejects_invalid_cursor() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_app_server_protocol::ModelProviderCapabilitiesReadParams;
|
||||
@@ -16,7 +16,7 @@ const DEFAULT_TIMEOUT: Duration = Duration::from_secs(30);
|
||||
#[tokio::test]
|
||||
async fn read_default_provider_capabilities() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -46,7 +46,7 @@ async fn read_amazon_bedrock_provider_capabilities() -> Result<()> {
|
||||
r#"model_provider = "amazon-bedrock"
|
||||
"#,
|
||||
)?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
@@ -32,7 +32,7 @@ async fn turn_start_accepts_output_schema_v2() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -114,7 +114,7 @@ async fn turn_start_output_schema_is_per_turn_v2() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use anyhow::Result;
|
||||
use anyhow::anyhow;
|
||||
use anyhow::bail;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::ItemCompletedNotification;
|
||||
@@ -53,7 +53,7 @@ async fn plan_mode_uses_proposed_plan_block_for_plan_item() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let turn = start_plan_mode_turn(&mut mcp).await?;
|
||||
@@ -111,7 +111,7 @@ async fn plan_mode_without_proposed_plan_does_not_emit_plan_item() -> Result<()>
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let _turn = start_plan_mode_turn(&mut mcp).await?;
|
||||
@@ -127,7 +127,9 @@ async fn plan_mode_without_proposed_plan_does_not_emit_plan_item() -> Result<()>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn start_plan_mode_turn(mcp: &mut McpProcess) -> Result<codex_app_server_protocol::Turn> {
|
||||
async fn start_plan_mode_turn(
|
||||
mcp: &mut AppServerTestProcess,
|
||||
) -> Result<codex_app_server_protocol::Turn> {
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
@@ -169,7 +171,7 @@ async fn start_plan_mode_turn(mcp: &mut McpProcess) -> Result<codex_app_server_p
|
||||
}
|
||||
|
||||
async fn collect_turn_notifications(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
) -> Result<(
|
||||
Vec<ThreadItem>,
|
||||
Vec<ThreadItem>,
|
||||
|
||||
@@ -5,9 +5,9 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::bail;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::DEFAULT_CLIENT_NAME;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::start_analytics_events_server;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
@@ -68,7 +68,7 @@ const TEST_ALLOW_HTTP_REMOTE_PLUGIN_BUNDLE_DOWNLOADS: &str =
|
||||
#[tokio::test]
|
||||
async fn plugin_install_rejects_relative_marketplace_paths() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -95,7 +95,7 @@ async fn plugin_install_rejects_relative_marketplace_paths() -> Result<()> {
|
||||
#[tokio::test]
|
||||
async fn plugin_install_rejects_missing_install_source() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -124,7 +124,7 @@ async fn plugin_install_rejects_missing_install_source() -> Result<()> {
|
||||
#[tokio::test]
|
||||
async fn plugin_install_rejects_multiple_install_sources() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -161,7 +161,7 @@ async fn plugin_install_rejects_remote_marketplace_when_plugins_are_disabled() -
|
||||
plugins = false
|
||||
"#,
|
||||
)?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -210,7 +210,7 @@ async fn plugin_install_writes_remote_plugin_to_cloud_and_cache() -> Result<()>
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[(TEST_ALLOW_HTTP_REMOTE_PLUGIN_BUNDLE_DOWNLOADS, Some("1"))],
|
||||
)
|
||||
@@ -273,7 +273,7 @@ async fn plugin_install_rejects_missing_remote_bundle_url() -> Result<()> {
|
||||
.await;
|
||||
mount_empty_remote_installed_plugins(&server).await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = send_remote_plugin_install_request(&mut mcp, REMOTE_PLUGIN_ID).await?;
|
||||
@@ -314,7 +314,7 @@ async fn plugin_install_rejects_plain_http_remote_bundle_url() -> Result<()> {
|
||||
mount_remote_plugin_detail(&server, REMOTE_PLUGIN_ID, "1.2.3", Some(&bundle_url)).await;
|
||||
mount_empty_remote_installed_plugins(&server).await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = send_remote_plugin_install_request(&mut mcp, REMOTE_PLUGIN_ID).await?;
|
||||
@@ -360,7 +360,7 @@ async fn plugin_install_rejects_invalid_remote_release_version() -> Result<()> {
|
||||
.await;
|
||||
mount_empty_remote_installed_plugins(&server).await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = send_remote_plugin_install_request(&mut mcp, REMOTE_PLUGIN_ID).await?;
|
||||
@@ -392,7 +392,7 @@ async fn plugin_install_rejects_invalid_remote_release_version() -> Result<()> {
|
||||
async fn plugin_install_rejects_invalid_remote_plugin_name() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
write_remote_plugin_catalog_config(codex_home.path(), "https://example.invalid/backend-api/")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -435,7 +435,7 @@ async fn plugin_install_rejects_remote_plugin_disabled_by_admin_before_download(
|
||||
.await;
|
||||
mount_empty_remote_installed_plugins(&server).await;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[(TEST_ALLOW_HTTP_REMOTE_PLUGIN_BUNDLE_DOWNLOADS, Some("1"))],
|
||||
)
|
||||
@@ -515,7 +515,7 @@ async fn plugin_install_rejects_when_workspace_codex_plugins_disabled() -> Resul
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -544,7 +544,7 @@ async fn plugin_install_rejects_when_workspace_codex_plugins_disabled() -> Resul
|
||||
#[tokio::test]
|
||||
async fn plugin_install_returns_invalid_request_for_missing_marketplace_file() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -585,7 +585,7 @@ async fn plugin_install_returns_invalid_request_for_not_available_plugin() -> Re
|
||||
let marketplace_path =
|
||||
AbsolutePathBuf::try_from(repo_root.path().join(".agents/plugins/marketplace.json"))?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -635,7 +635,8 @@ async fn plugin_install_returns_invalid_request_for_disallowed_product_plugin()
|
||||
AbsolutePathBuf::try_from(repo_root.path().join(".agents/plugins/marketplace.json"))?;
|
||||
|
||||
let mut mcp =
|
||||
McpProcess::new_with_args(codex_home.path(), &["--session-source", "atlas"]).await?;
|
||||
AppServerTestProcess::new_with_args(codex_home.path(), &["--session-source", "atlas"])
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -684,7 +685,7 @@ async fn plugin_install_tracks_analytics_event() -> Result<()> {
|
||||
let marketplace_path =
|
||||
AbsolutePathBuf::try_from(repo_root.path().join(".agents/plugins/marketplace.json"))?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -739,7 +740,7 @@ async fn plugin_install_tracks_remote_plugin_analytics_event() -> Result<()> {
|
||||
mount_remote_plugin_install(&server, REMOTE_PLUGIN_ID).await;
|
||||
mount_backend_analytics_events(&server).await;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[(TEST_ALLOW_HTTP_REMOTE_PLUGIN_BUNDLE_DOWNLOADS, Some("1"))],
|
||||
)
|
||||
@@ -791,7 +792,7 @@ async fn plugin_install_errors_when_remote_bundle_download_fails() -> Result<()>
|
||||
mount_empty_remote_installed_plugins(&server).await;
|
||||
mount_remote_plugin_install(&server, REMOTE_PLUGIN_ID).await;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[(TEST_ALLOW_HTTP_REMOTE_PLUGIN_BUNDLE_DOWNLOADS, Some("1"))],
|
||||
)
|
||||
@@ -891,7 +892,7 @@ async fn plugin_install_returns_apps_needing_auth() -> Result<()> {
|
||||
let marketplace_path =
|
||||
AbsolutePathBuf::try_from(repo_root.path().join(".agents/plugins/marketplace.json"))?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -975,7 +976,7 @@ async fn plugin_install_filters_disallowed_apps_needing_auth() -> Result<()> {
|
||||
let marketplace_path =
|
||||
AbsolutePathBuf::try_from(repo_root.path().join(".agents/plugins/marketplace.json"))?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -1042,7 +1043,7 @@ async fn plugin_install_makes_bundled_mcp_servers_available_to_followup_requests
|
||||
let marketplace_path =
|
||||
AbsolutePathBuf::try_from(repo_root.path().join(".agents/plugins/marketplace.json"))?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -1461,7 +1462,7 @@ async fn mount_remote_plugin_install_after_cache_write(
|
||||
}
|
||||
|
||||
async fn send_remote_plugin_install_request(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
remote_plugin_id: &str,
|
||||
) -> Result<i64> {
|
||||
mcp.send_plugin_install_request(PluginInstallParams {
|
||||
|
||||
@@ -2,8 +2,8 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::bail;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
@@ -79,7 +79,7 @@ async fn plugin_list_skips_invalid_marketplace_file_and_reports_error() -> Resul
|
||||
std::fs::write(marketplace_path.as_path(), "{not json")?;
|
||||
|
||||
let home = codex_home.path().to_string_lossy().into_owned();
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("HOME", Some(home.as_str())),
|
||||
@@ -128,7 +128,7 @@ async fn plugin_list_skips_invalid_marketplace_file_and_reports_error() -> Resul
|
||||
#[tokio::test]
|
||||
async fn plugin_list_rejects_relative_cwds() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -205,7 +205,7 @@ async fn plugin_list_keeps_valid_marketplaces_when_another_marketplace_fails_to_
|
||||
std::fs::write(invalid_marketplace_path.as_path(), "{not json")?;
|
||||
|
||||
let home = codex_home.path().to_string_lossy().into_owned();
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("HOME", Some(home.as_str())),
|
||||
@@ -321,7 +321,7 @@ async fn plugin_list_returns_empty_when_workspace_codex_plugins_disabled() -> Re
|
||||
.await;
|
||||
|
||||
let home = codex_home.path().to_string_lossy().into_owned();
|
||||
let mut mcp = McpProcess::new_without_managed_config_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_without_managed_config_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("HOME", Some(home.as_str())),
|
||||
@@ -412,7 +412,7 @@ async fn plugin_list_reuses_cached_workspace_codex_plugins_setting() -> Result<(
|
||||
.await;
|
||||
|
||||
let home = codex_home.path().to_string_lossy().into_owned();
|
||||
let mut mcp = McpProcess::new_without_managed_config_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_without_managed_config_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("HOME", Some(home.as_str())),
|
||||
@@ -497,7 +497,7 @@ async fn plugin_list_uses_alternate_discoverable_manifest_and_keeps_undiscoverab
|
||||
)?;
|
||||
|
||||
let home = codex_home.path().to_string_lossy().into_owned();
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("HOME", Some(home.as_str())),
|
||||
@@ -608,7 +608,7 @@ async fn plugin_list_accepts_omitted_cwds() -> Result<()> {
|
||||
}"#,
|
||||
)?;
|
||||
let home = codex_home.path().to_string_lossy().into_owned();
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("HOME", Some(home.as_str())),
|
||||
@@ -668,7 +668,7 @@ async fn plugin_list_returns_share_context_for_shared_local_plugin() -> Result<(
|
||||
&AbsolutePathBuf::try_from(plugin_root)?,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -758,7 +758,7 @@ enabled = false
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -905,7 +905,7 @@ enabled = false
|
||||
|
||||
let workspace_default = TempDir::new()?;
|
||||
let home = codex_home.path().to_string_lossy().into_owned();
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("HOME", Some(home.as_str())),
|
||||
@@ -999,7 +999,7 @@ async fn plugin_list_returns_plugin_interface_with_absolute_asset_paths() -> Res
|
||||
}"##,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -1112,7 +1112,7 @@ async fn plugin_list_accepts_legacy_string_default_prompt() -> Result<()> {
|
||||
}"##,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -1200,7 +1200,7 @@ enabled = true
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -1303,7 +1303,8 @@ async fn app_server_startup_remote_plugin_sync_runs_once() -> Result<()> {
|
||||
.join(STARTUP_REMOTE_PLUGIN_SYNC_MARKER_FILE);
|
||||
|
||||
{
|
||||
let mut mcp = McpProcess::new_with_plugin_startup_tasks(codex_home.path()).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_plugin_startup_tasks(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
wait_for_path_exists(&marker_path).await?;
|
||||
@@ -1342,7 +1343,8 @@ async fn app_server_startup_remote_plugin_sync_runs_once() -> Result<()> {
|
||||
assert!(config.contains(r#"[plugins."linear@openai-curated"]"#));
|
||||
|
||||
{
|
||||
let mut mcp = McpProcess::new_with_plugin_startup_tasks(codex_home.path()).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_plugin_startup_tasks(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
}
|
||||
|
||||
@@ -1383,7 +1385,7 @@ async fn app_server_startup_sync_downloads_remote_installed_plugin_bundles() ->
|
||||
let installed_path = codex_home
|
||||
.path()
|
||||
.join("plugins/cache/chatgpt-global/linear/1.2.3");
|
||||
let mut mcp = McpProcess::new_with_env_and_plugin_startup_tasks(
|
||||
let mut mcp = AppServerTestProcess::new_with_env_and_plugin_startup_tasks(
|
||||
codex_home.path(),
|
||||
&[(TEST_ALLOW_HTTP_REMOTE_PLUGIN_BUNDLE_DOWNLOADS, Some("1"))],
|
||||
)
|
||||
@@ -1438,7 +1440,7 @@ async fn plugin_list_sync_upgrades_and_removes_remote_installed_plugin_bundles()
|
||||
.join("plugins/cache/chatgpt-global/linear/1.2.3");
|
||||
let stale_path = codex_home.path().join("plugins/cache/chatgpt-global/stale");
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[(TEST_ALLOW_HTTP_REMOTE_PLUGIN_BUNDLE_DOWNLOADS, Some("1"))],
|
||||
)
|
||||
@@ -1598,7 +1600,7 @@ async fn plugin_list_includes_remote_marketplaces_when_remote_plugin_enabled() -
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -1678,7 +1680,7 @@ async fn plugin_list_does_not_append_global_remote_when_marketplace_kinds_are_ex
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -1739,7 +1741,7 @@ async fn plugin_list_fetches_workspace_directory_kind_without_remote_plugin_flag
|
||||
mount_remote_plugin_list(&server, "WORKSPACE", &workspace_plugin_body).await;
|
||||
mount_remote_installed_plugins(&server, "WORKSPACE", &workspace_installed_body).await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -1829,7 +1831,7 @@ async fn plugin_list_fetches_shared_with_me_kind() -> Result<()> {
|
||||
mount_shared_workspace_plugins(&server, &shared_plugin_body).await;
|
||||
mount_remote_installed_plugins(&server, "WORKSPACE", &workspace_installed_body).await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -1992,7 +1994,7 @@ async fn plugin_list_marks_remote_plugin_disabled_by_admin() -> Result<()> {
|
||||
.await;
|
||||
}
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -2120,7 +2122,7 @@ async fn plugin_list_remote_marketplace_replaces_local_marketplace_with_same_nam
|
||||
.await;
|
||||
}
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -2179,7 +2181,7 @@ remote_plugin = true
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -2215,7 +2217,7 @@ async fn plugin_list_fetches_featured_plugin_ids_without_chatgpt_auth() -> Resul
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -2254,7 +2256,7 @@ async fn plugin_list_uses_warmed_featured_plugin_ids_cache_on_first_request() ->
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new_with_plugin_startup_tasks(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_with_plugin_startup_tasks(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
wait_for_featured_plugin_request_count(&server, /*expected_count*/ 1).await?;
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ use std::sync::Mutex as StdMutex;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
use axum::Json;
|
||||
@@ -64,7 +64,7 @@ const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
#[tokio::test]
|
||||
async fn plugin_read_rejects_missing_read_source() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -93,7 +93,7 @@ async fn plugin_read_rejects_missing_read_source() -> Result<()> {
|
||||
#[tokio::test]
|
||||
async fn plugin_read_rejects_multiple_read_sources() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -190,7 +190,7 @@ plugins = true
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -296,7 +296,7 @@ async fn plugin_read_returns_share_context_for_shared_remote_plugin() -> Result<
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -468,7 +468,7 @@ async fn plugin_read_reads_remote_plugin_details_when_remote_plugin_enabled() ->
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -553,7 +553,7 @@ async fn plugin_skill_read_reads_remote_skill_contents_when_remote_plugin_enable
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -605,7 +605,7 @@ async fn plugin_read_maps_missing_remote_plugin_to_invalid_request() -> Result<(
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -657,7 +657,7 @@ remote_plugin = true
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -687,7 +687,7 @@ remote_plugin = true
|
||||
async fn plugin_read_rejects_invalid_remote_plugin_name() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
write_remote_plugin_catalog_config(codex_home.path(), "https://example.invalid/backend-api/")?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -745,7 +745,7 @@ enabled = true
|
||||
)?;
|
||||
write_installed_plugin(&codex_home, "openai-curated", "demo-plugin")?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let marketplace_path =
|
||||
@@ -844,7 +844,7 @@ async fn plugin_read_returns_share_context_for_shared_local_plugin() -> Result<(
|
||||
.expect(1)
|
||||
.mount(&server)
|
||||
.await;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -920,7 +920,7 @@ async fn plugin_read_falls_back_to_local_share_context_without_remote_auth() ->
|
||||
let plugin_path = AbsolutePathBuf::try_from(repo_root.path().join("demo-plugin"))?;
|
||||
write_plugin_share_local_path_mapping(codex_home.path(), "plugins_123", &plugin_path)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -976,7 +976,7 @@ async fn plugin_read_fails_on_malformed_share_mapping() -> Result<()> {
|
||||
"not valid json\n",
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -1169,7 +1169,7 @@ enabled = false
|
||||
)?;
|
||||
write_installed_plugin(&codex_home, "codex-curated", "demo-plugin")?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let marketplace_path =
|
||||
@@ -1340,7 +1340,7 @@ async fn plugin_read_returns_app_needs_auth() -> Result<()> {
|
||||
let marketplace_path =
|
||||
AbsolutePathBuf::try_from(repo_root.path().join(".agents/plugins/marketplace.json"))?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -1407,7 +1407,7 @@ async fn plugin_read_accepts_legacy_string_default_prompt() -> Result<()> {
|
||||
)?;
|
||||
write_plugins_enabled_config(&codex_home)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -1469,7 +1469,7 @@ async fn plugin_read_describes_uninstalled_git_source_without_cloning() -> Resul
|
||||
)?;
|
||||
write_plugins_enabled_config(&codex_home)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -1532,7 +1532,7 @@ async fn plugin_read_returns_invalid_request_when_plugin_is_missing() -> Result<
|
||||
)?;
|
||||
write_plugins_enabled_config(&codex_home)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -1585,7 +1585,7 @@ async fn plugin_read_returns_invalid_request_when_plugin_manifest_is_missing() -
|
||||
)?;
|
||||
write_plugins_enabled_config(&codex_home)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
|
||||
@@ -3,8 +3,8 @@ use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
use codex_app_server_protocol::JSONRPCError;
|
||||
@@ -95,7 +95,7 @@ async fn plugin_share_save_uploads_local_plugin() -> Result<()> {
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
let expected_plugin_path = AbsolutePathBuf::try_from(plugin_path.clone())?;
|
||||
let request_id = mcp
|
||||
@@ -243,7 +243,7 @@ async fn plugin_share_save_forwards_access_policy() -> Result<()> {
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
let expected_plugin_path = AbsolutePathBuf::try_from(plugin_path)?;
|
||||
let request_id = mcp
|
||||
@@ -296,7 +296,7 @@ async fn plugin_share_save_rejects_listed_discoverability() -> Result<()> {
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
let request_id = mcp
|
||||
.send_raw_request(
|
||||
@@ -338,7 +338,7 @@ async fn plugin_share_rejects_workspace_targets_from_client() -> Result<()> {
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
let request_id = mcp
|
||||
.send_raw_request(
|
||||
@@ -416,7 +416,7 @@ async fn plugin_share_save_rejects_access_policy_for_existing_plugin() -> Result
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
let request_id = mcp
|
||||
.send_raw_request(
|
||||
@@ -489,7 +489,7 @@ async fn plugin_share_list_returns_created_workspace_plugins() -> Result<()> {
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
let request_id = mcp
|
||||
.send_raw_request("plugin/share/list", Some(json!({})))
|
||||
@@ -587,7 +587,7 @@ async fn plugin_share_update_targets_updates_share_targets() -> Result<()> {
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
let request_id = mcp
|
||||
.send_raw_request(
|
||||
@@ -667,7 +667,7 @@ async fn plugin_share_delete_removes_created_workspace_plugin() -> Result<()> {
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
let request_id = mcp
|
||||
.send_raw_request(
|
||||
|
||||
@@ -2,9 +2,9 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::bail;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::DEFAULT_CLIENT_NAME;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::start_analytics_events_server;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
@@ -42,7 +42,7 @@ enabled = true
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let params = PluginUninstallParams {
|
||||
@@ -100,7 +100,7 @@ async fn plugin_uninstall_tracks_analytics_event() -> Result<()> {
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -161,7 +161,7 @@ async fn plugin_uninstall_rejects_remote_plugin_when_plugins_are_disabled() -> R
|
||||
plugins = false
|
||||
"#,
|
||||
)?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -230,7 +230,7 @@ async fn plugin_uninstall_writes_remote_plugin_to_cloud_when_remote_plugin_enabl
|
||||
.join(format!("plugins/cache/chatgpt-global/{REMOTE_PLUGIN_ID}"));
|
||||
std::fs::create_dir_all(legacy_remote_plugin_cache_root.join("local/.codex-plugin"))?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -302,7 +302,7 @@ async fn plugin_uninstall_uses_detail_scope_for_cache_namespace() -> Result<()>
|
||||
.join("plugins/cache/chatgpt-global/linear");
|
||||
std::fs::create_dir_all(global_cache_root.join("1.0.0/.codex-plugin"))?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -376,7 +376,7 @@ async fn plugin_uninstall_accepts_workspace_remote_plugin_id_shape() -> Result<(
|
||||
r#"{"name":"skill-improver","version":"1.0.0"}"#,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -425,7 +425,7 @@ async fn plugin_uninstall_rejects_before_post_when_remote_detail_fetch_fails() -
|
||||
.join(format!("plugins/cache/chatgpt-global/{REMOTE_PLUGIN_ID}"));
|
||||
std::fs::create_dir_all(legacy_remote_plugin_cache_root.join("local/.codex-plugin"))?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -467,7 +467,7 @@ async fn plugin_uninstall_rejects_remote_plugin_id_with_spaces_before_network_ca
|
||||
codex_home.path(),
|
||||
&format!("{}/backend-api/", server.uri()),
|
||||
)?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -502,7 +502,7 @@ async fn plugin_uninstall_rejects_invalid_remote_plugin_id_before_network_call()
|
||||
codex_home.path(),
|
||||
&format!("{}/backend-api/", server.uri()),
|
||||
)?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -537,7 +537,7 @@ async fn plugin_uninstall_rejects_empty_remote_plugin_id() -> Result<()> {
|
||||
codex_home.path(),
|
||||
&format!("{}/backend-api/", server.uri()),
|
||||
)?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
use codex_app_server_protocol::ProcessExitedNotification;
|
||||
use codex_app_server_protocol::ProcessKillParams;
|
||||
@@ -202,10 +202,10 @@ async fn process_kill_terminates_running_process() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn initialized_mcp(codex_home: &Path) -> Result<(MockServer, McpProcess)> {
|
||||
async fn initialized_mcp(codex_home: &Path) -> Result<(MockServer, AppServerTestProcess)> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
|
||||
create_config_toml(codex_home, &server.uri(), "never")?;
|
||||
let mut mcp = McpProcess::new(codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
Ok((server, mcp))
|
||||
}
|
||||
@@ -229,7 +229,7 @@ fn process_spawn_params(
|
||||
})
|
||||
}
|
||||
|
||||
async fn read_process_exited(mcp: &mut McpProcess) -> Result<ProcessExitedNotification> {
|
||||
async fn read_process_exited(mcp: &mut AppServerTestProcess) -> Result<ProcessExitedNotification> {
|
||||
let notification = mcp
|
||||
.read_stream_until_notification_message("process/exited")
|
||||
.await?;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
use codex_app_server_protocol::AddCreditsNudgeCreditType;
|
||||
@@ -37,7 +37,8 @@ const INTERNAL_ERROR_CODE: i64 = -32603;
|
||||
async fn get_account_rate_limits_requires_auth() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp.send_get_account_rate_limits_request().await?;
|
||||
@@ -62,7 +63,7 @@ async fn get_account_rate_limits_requires_auth() -> Result<()> {
|
||||
async fn get_account_rate_limits_requires_chatgpt_auth() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
login_with_api_key(&mut mcp, "sk-test-key").await?;
|
||||
@@ -153,7 +154,8 @@ async fn get_account_rate_limits_returns_snapshot() -> Result<()> {
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp.send_get_account_rate_limits_request().await?;
|
||||
@@ -238,7 +240,8 @@ async fn get_account_rate_limits_returns_snapshot() -> Result<()> {
|
||||
async fn send_add_credits_nudge_email_requires_auth() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -267,7 +270,7 @@ async fn send_add_credits_nudge_email_requires_auth() -> Result<()> {
|
||||
async fn send_add_credits_nudge_email_requires_chatgpt_auth() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
login_with_api_key(&mut mcp, "sk-test-key").await?;
|
||||
@@ -321,7 +324,8 @@ async fn send_add_credits_nudge_email_posts_expected_body() -> Result<()> {
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -364,7 +368,8 @@ async fn send_add_credits_nudge_email_maps_cooldown() -> Result<()> {
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -407,7 +412,8 @@ async fn send_add_credits_nudge_email_surfaces_backend_failure() -> Result<()> {
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -437,7 +443,7 @@ async fn send_add_credits_nudge_email_surfaces_backend_failure() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn login_with_api_key(mcp: &mut McpProcess, api_key: &str) -> Result<()> {
|
||||
async fn login_with_api_key(mcp: &mut AppServerTestProcess, api_key: &str) -> Result<()> {
|
||||
let request_id = mcp.send_login_account_api_key_request(api_key).await?;
|
||||
let response: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
use app_test_support::create_shell_command_sse_response;
|
||||
@@ -191,7 +191,7 @@ struct RealtimeSidebandScript {
|
||||
}
|
||||
|
||||
struct RealtimeE2eHarness {
|
||||
mcp: McpProcess,
|
||||
mcp: AppServerTestProcess,
|
||||
_codex_home: TempDir,
|
||||
main_loop_responses_server: MockServer,
|
||||
realtime_server: WebSocketTestServer,
|
||||
@@ -280,7 +280,7 @@ impl RealtimeE2eHarness {
|
||||
sandbox,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
login_with_api_key(&mut mcp, "sk-test-key").await?;
|
||||
|
||||
@@ -539,7 +539,7 @@ async fn realtime_conversation_streams_v2_notifications() -> Result<()> {
|
||||
StartupContextConfig::Generated,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
login_with_api_key(&mut mcp, "sk-test-key").await?;
|
||||
|
||||
@@ -788,7 +788,7 @@ async fn realtime_text_output_modality_requests_text_output_and_final_transcript
|
||||
StartupContextConfig::Generated,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
login_with_api_key(&mut mcp, "sk-test-key").await?;
|
||||
|
||||
@@ -890,7 +890,7 @@ async fn realtime_list_voices_returns_supported_names() -> Result<()> {
|
||||
StartupContextConfig::Generated,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -962,7 +962,7 @@ async fn realtime_conversation_stop_emits_closed_notification() -> Result<()> {
|
||||
StartupContextConfig::Generated,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
login_with_api_key(&mut mcp, "sk-test-key").await?;
|
||||
|
||||
@@ -1058,7 +1058,7 @@ async fn realtime_webrtc_start_emits_sdp_notification() -> Result<()> {
|
||||
StartupContextConfig::Override("startup context"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
login_with_api_key(&mut mcp, "sk-test-key").await?;
|
||||
|
||||
@@ -1973,7 +1973,7 @@ async fn realtime_webrtc_start_surfaces_backend_error() -> Result<()> {
|
||||
StartupContextConfig::Override("startup context"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
login_with_api_key(&mut mcp, "sk-test-key").await?;
|
||||
|
||||
@@ -2034,7 +2034,7 @@ async fn realtime_conversation_requires_feature_flag() -> Result<()> {
|
||||
StartupContextConfig::Generated,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_start_request_id = mcp
|
||||
@@ -2074,7 +2074,10 @@ async fn realtime_conversation_requires_feature_flag() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn read_notification<T: DeserializeOwned>(mcp: &mut McpProcess, method: &str) -> Result<T> {
|
||||
async fn read_notification<T: DeserializeOwned>(
|
||||
mcp: &mut AppServerTestProcess,
|
||||
method: &str,
|
||||
) -> Result<T> {
|
||||
let notification = timeout(
|
||||
DEFAULT_TIMEOUT,
|
||||
mcp.read_stream_until_notification_message(method),
|
||||
@@ -2086,7 +2089,7 @@ async fn read_notification<T: DeserializeOwned>(mcp: &mut McpProcess, method: &s
|
||||
Ok(serde_json::from_value(params)?)
|
||||
}
|
||||
|
||||
async fn login_with_api_key(mcp: &mut McpProcess, api_key: &str) -> Result<()> {
|
||||
async fn login_with_api_key(mcp: &mut AppServerTestProcess, api_key: &str) -> Result<()> {
|
||||
let request_id = mcp.send_login_account_api_key_request(api_key).await?;
|
||||
let response: JSONRPCResponse = timeout(
|
||||
DEFAULT_TIMEOUT,
|
||||
@@ -2100,7 +2103,7 @@ async fn login_with_api_key(mcp: &mut McpProcess, api_key: &str) -> Result<()> {
|
||||
}
|
||||
|
||||
async fn wait_for_started_command_execution(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
) -> Result<ItemStartedNotification> {
|
||||
loop {
|
||||
let started = read_notification::<ItemStartedNotification>(mcp, "item/started").await?;
|
||||
@@ -2111,7 +2114,7 @@ async fn wait_for_started_command_execution(
|
||||
}
|
||||
|
||||
async fn wait_for_completed_command_execution(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
) -> Result<ItemCompletedNotification> {
|
||||
loop {
|
||||
let completed =
|
||||
|
||||
@@ -84,6 +84,7 @@ async fn thread_start_with_non_local_thread_store_does_not_create_local_persiste
|
||||
config_warnings: Vec::new(),
|
||||
session_source: SessionSource::Cli,
|
||||
enable_codex_api_key_env: false,
|
||||
plugin_startup_tasks: codex_app_server::PluginStartupTasks::Start,
|
||||
initialize: InitializeParams {
|
||||
client_info: ClientInfo {
|
||||
name: "codex-app-server-tests".to_string(),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
use app_test_support::create_mock_responses_server_sequence;
|
||||
use app_test_support::create_request_permissions_sse_response;
|
||||
@@ -30,7 +30,7 @@ async fn request_permissions_round_trip() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence(responses).await;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_start_id = mcp
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
use app_test_support::create_mock_responses_server_sequence;
|
||||
use app_test_support::create_request_user_input_sse_response;
|
||||
@@ -32,7 +32,7 @@ async fn request_user_input_round_trip() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence(responses).await;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_start_id = mcp
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
use app_test_support::create_mock_responses_server_repeating_assistant;
|
||||
use app_test_support::create_mock_responses_server_sequence;
|
||||
@@ -59,7 +59,7 @@ async fn review_start_runs_review_turn_and_emits_code_review_item() -> Result<()
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_id = start_default_thread(&mut mcp).await?;
|
||||
@@ -172,7 +172,7 @@ async fn review_start_exec_approval_item_id_matches_command_execution_item() ->
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml_with_approval_policy(codex_home.path(), &server.uri(), "untrusted")?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_id = start_default_thread(&mut mcp).await?;
|
||||
@@ -254,7 +254,7 @@ async fn review_start_rejects_empty_base_branch() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
let thread_id = start_default_thread(&mut mcp).await?;
|
||||
|
||||
@@ -297,7 +297,7 @@ async fn review_start_with_detached_delivery_returns_new_thread_id() -> Result<(
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_id = start_default_thread(&mut mcp).await?;
|
||||
@@ -374,7 +374,7 @@ async fn review_start_rejects_empty_commit_sha() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
let thread_id = start_default_thread(&mut mcp).await?;
|
||||
|
||||
@@ -409,7 +409,7 @@ async fn review_start_rejects_empty_custom_instructions() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
let thread_id = start_default_thread(&mut mcp).await?;
|
||||
|
||||
@@ -440,7 +440,7 @@ async fn review_start_rejects_empty_custom_instructions() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn start_default_thread(mcp: &mut McpProcess) -> Result<String> {
|
||||
async fn start_default_thread(mcp: &mut AppServerTestProcess) -> Result<String> {
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
@@ -461,7 +461,7 @@ async fn start_default_thread(mcp: &mut McpProcess) -> Result<String> {
|
||||
Ok(thread.id)
|
||||
}
|
||||
|
||||
async fn materialize_thread_rollout(mcp: &mut McpProcess, thread_id: &str) -> Result<()> {
|
||||
async fn materialize_thread_rollout(mcp: &mut AppServerTestProcess, thread_id: &str) -> Result<()> {
|
||||
let turn_req = mcp
|
||||
.send_turn_start_request(TurnStartParams {
|
||||
thread_id: thread_id.to_string(),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::CodexErrorInfo;
|
||||
use codex_app_server_protocol::ErrorNotification;
|
||||
@@ -48,7 +48,7 @@ async fn openai_model_header_mismatch_emits_model_rerouted_notification_v2() ->
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -114,7 +114,7 @@ async fn cyber_policy_response_emits_typed_error_notification_v2() -> Result<()>
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -190,7 +190,7 @@ async fn response_model_field_mismatch_emits_model_rerouted_notification_v2_when
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -258,7 +258,7 @@ async fn model_verification_emits_typed_notification_and_warning_v2() -> Result<
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -306,7 +306,7 @@ async fn model_verification_emits_typed_notification_and_warning_v2() -> Result<
|
||||
}
|
||||
|
||||
async fn collect_turn_notifications_and_validate_no_warning_item(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
) -> Result<ModelReroutedNotification> {
|
||||
let mut rerouted = None;
|
||||
|
||||
@@ -348,7 +348,7 @@ async fn collect_turn_notifications_and_validate_no_warning_item(
|
||||
}
|
||||
|
||||
async fn collect_model_verification_notifications_and_validate_no_warning_item(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
) -> Result<ModelVerificationNotification> {
|
||||
let mut verification = None;
|
||||
|
||||
@@ -399,7 +399,7 @@ async fn collect_model_verification_notifications_and_validate_no_warning_item(
|
||||
}
|
||||
|
||||
async fn collect_cyber_policy_error_and_validate_no_reroute(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
) -> Result<ErrorNotification> {
|
||||
let mut error = None;
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::create_mock_responses_server_repeating_assistant;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
@@ -222,7 +222,7 @@ async fn skills_list_loads_remote_installed_plugin_skills_from_cache() -> Result
|
||||
.mount(&server)
|
||||
.await;
|
||||
}
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let stale_skills_list_request_id = mcp
|
||||
@@ -346,7 +346,7 @@ async fn skills_list_excludes_plugin_skills_when_workspace_codex_plugins_disable
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -392,7 +392,7 @@ async fn skills_list_skips_cwd_roots_when_environment_disabled() -> Result<()> {
|
||||
"---\nname: repo-skill\ndescription: from repo root\n---\n\n# Body\n",
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[(CODEX_EXEC_SERVER_URL_ENV_VAR, Some("none"))],
|
||||
)
|
||||
@@ -436,7 +436,7 @@ async fn skills_list_accepts_relative_cwds() -> Result<()> {
|
||||
let relative_cwd = std::path::PathBuf::from("relative-cwd");
|
||||
std::fs::create_dir_all(codex_home.path().join(&relative_cwd))?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -464,7 +464,7 @@ async fn skills_list_preserves_requested_cwd_order() -> Result<()> {
|
||||
let first_cwd = TempDir::new()?;
|
||||
let second_cwd = TempDir::new()?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -500,7 +500,7 @@ async fn skills_list_uses_cached_result_until_force_reload() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let cwd = TempDir::new()?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
// Seed the cwd cache before the cwd-local skill exists.
|
||||
@@ -584,9 +584,11 @@ async fn skills_changed_notification_is_emitted_after_skill_change() -> Result<(
|
||||
)?;
|
||||
write_skill(&codex_home, "demo")?;
|
||||
|
||||
let mut mcp =
|
||||
McpProcess::new_with_env(codex_home.path(), &[(CODEX_EXEC_SERVER_URL_ENV_VAR, None)])
|
||||
.await?;
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[(CODEX_EXEC_SERVER_URL_ENV_VAR, None)],
|
||||
)
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
let initial_skills_request_id = mcp
|
||||
.send_skills_list_request(SkillsListParams {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_fake_rollout;
|
||||
use app_test_support::create_mock_responses_server_repeating_assistant;
|
||||
use app_test_support::to_response;
|
||||
@@ -38,7 +38,7 @@ async fn thread_archive_requires_materialized_rollout() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
// Start a thread.
|
||||
@@ -220,7 +220,7 @@ async fn thread_archive_archives_spawned_descendants() -> Result<()> {
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let archive_id = mcp
|
||||
@@ -341,7 +341,7 @@ async fn thread_archive_succeeds_when_descendant_archive_fails() -> Result<()> {
|
||||
.join(child_rollout_path.file_name().expect("rollout file name"));
|
||||
std::fs::create_dir_all(&archived_child_path)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let archive_id = mcp
|
||||
@@ -445,7 +445,7 @@ async fn thread_archive_succeeds_when_spawned_descendant_is_missing() -> Result<
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let archive_id = mcp
|
||||
@@ -498,7 +498,7 @@ async fn thread_archive_clears_stale_subscriptions_before_resume() -> Result<()>
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut primary = McpProcess::new(codex_home.path()).await?;
|
||||
let mut primary = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
@@ -537,7 +537,7 @@ async fn thread_archive_clears_stale_subscriptions_before_resume() -> Result<()>
|
||||
.await??;
|
||||
primary.clear_message_buffer();
|
||||
|
||||
let mut secondary = McpProcess::new(codex_home.path()).await?;
|
||||
let mut secondary = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, secondary.initialize()).await??;
|
||||
|
||||
let archive_id = primary
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::create_fake_rollout;
|
||||
use app_test_support::create_fake_rollout_with_token_usage;
|
||||
use app_test_support::create_mock_responses_server_repeating_assistant;
|
||||
@@ -83,7 +83,7 @@ async fn thread_fork_creates_new_thread_and_emits_started() -> Result<()> {
|
||||
);
|
||||
let original_contents = std::fs::read_to_string(&original_path)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let fork_id = mcp
|
||||
@@ -241,7 +241,7 @@ async fn thread_fork_can_load_source_by_path() -> Result<()> {
|
||||
"rollout-2025-01-05T12-00-00-{conversation_id}.jsonl"
|
||||
));
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let fork_id = mcp
|
||||
@@ -281,7 +281,7 @@ async fn thread_fork_emits_restored_token_usage_before_next_turn() -> Result<()>
|
||||
Some("mock_provider"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let fork_id = mcp
|
||||
@@ -335,7 +335,7 @@ async fn thread_fork_can_exclude_turns_and_skip_restored_token_usage() -> Result
|
||||
Some("mock_provider"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let fork_id = mcp
|
||||
@@ -386,7 +386,7 @@ async fn thread_fork_tracks_thread_initialized_analytics() -> Result<()> {
|
||||
/*git_info*/ None,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let fork_id = mcp
|
||||
@@ -415,7 +415,7 @@ async fn thread_fork_rejects_unmaterialized_thread() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -503,7 +503,7 @@ async fn thread_fork_surfaces_cloud_requirements_load_errors() -> Result<()> {
|
||||
)?;
|
||||
|
||||
let refresh_token_url = format!("{}/oauth/token", server.uri());
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("OPENAI_API_KEY", None),
|
||||
@@ -566,7 +566,7 @@ async fn thread_fork_ephemeral_remains_pathless_and_omits_listing() -> Result<()
|
||||
/*git_info*/ None,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let fork_id = mcp
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
@@ -36,7 +36,7 @@ async fn thread_inject_items_adds_raw_response_items_to_thread_history() -> Resu
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -151,7 +151,7 @@ async fn thread_inject_items_adds_raw_response_items_after_a_turn() -> Result<()
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_fake_rollout;
|
||||
use app_test_support::create_fake_rollout_with_source;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
@@ -46,14 +46,14 @@ use uuid::Uuid;
|
||||
|
||||
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
|
||||
|
||||
async fn init_mcp(codex_home: &Path) -> Result<McpProcess> {
|
||||
let mut mcp = McpProcess::new(codex_home).await?;
|
||||
async fn init_mcp(codex_home: &Path) -> Result<AppServerTestProcess> {
|
||||
let mut mcp = AppServerTestProcess::new(codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
Ok(mcp)
|
||||
}
|
||||
|
||||
async fn list_threads(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
cursor: Option<String>,
|
||||
limit: Option<u32>,
|
||||
providers: Option<Vec<String>>,
|
||||
@@ -73,7 +73,7 @@ async fn list_threads(
|
||||
}
|
||||
|
||||
async fn list_threads_with_sort(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
cursor: Option<String>,
|
||||
limit: Option<u32>,
|
||||
providers: Option<Vec<String>>,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_mock_responses_server_repeating_assistant;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
@@ -21,7 +21,7 @@ async fn thread_loaded_list_returns_loaded_thread_ids() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_id = start_thread(&mut mcp).await?;
|
||||
@@ -51,7 +51,7 @@ async fn thread_loaded_list_paginates() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let first = start_thread(&mut mcp).await?;
|
||||
@@ -122,7 +122,7 @@ stream_max_retries = 0
|
||||
)
|
||||
}
|
||||
|
||||
async fn start_thread(mcp: &mut McpProcess) -> Result<String> {
|
||||
async fn start_thread(mcp: &mut AppServerTestProcess) -> Result<String> {
|
||||
let req_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
model: Some("gpt-5.2".to_string()),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_fake_rollout;
|
||||
use app_test_support::create_mock_responses_server_repeating_assistant;
|
||||
use app_test_support::to_response;
|
||||
@@ -27,7 +27,7 @@ async fn thread_memory_mode_set_updates_loaded_thread_state() -> Result<()> {
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
let state_db = init_state_db(codex_home.path()).await?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -79,7 +79,7 @@ async fn thread_memory_mode_set_updates_stored_thread_state() -> Result<()> {
|
||||
)?;
|
||||
let thread_uuid = ThreadId::from_string(&thread_id)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
for mode in [ThreadMemoryMode::Disabled, ThreadMemoryMode::Enabled] {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_fake_rollout;
|
||||
use app_test_support::create_mock_responses_server_repeating_assistant;
|
||||
use app_test_support::rollout_path;
|
||||
@@ -41,7 +41,7 @@ async fn thread_metadata_update_patches_git_branch_and_returns_updated_thread()
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -136,7 +136,7 @@ async fn thread_metadata_update_rejects_empty_git_info_patch() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -182,7 +182,7 @@ async fn thread_metadata_update_rejects_ephemeral_thread() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -244,7 +244,7 @@ async fn thread_metadata_update_repairs_missing_sqlite_row_for_stored_thread() -
|
||||
/*git_info*/ None,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let update_id = mcp
|
||||
@@ -309,7 +309,7 @@ async fn thread_metadata_update_repairs_loaded_thread_without_resetting_summary(
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let resume_id = mcp
|
||||
@@ -387,7 +387,7 @@ async fn thread_metadata_update_repairs_missing_sqlite_row_for_archived_thread()
|
||||
);
|
||||
fs::rename(&archived_source, &archived_dest)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let update_id = mcp
|
||||
@@ -443,7 +443,7 @@ async fn thread_metadata_update_can_clear_stored_git_fields() -> Result<()> {
|
||||
)?;
|
||||
let _state_db = init_state_db(codex_home.path()).await?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let update_id = mcp
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_fake_rollout_with_text_elements;
|
||||
use app_test_support::create_mock_responses_server_repeating_assistant;
|
||||
use app_test_support::rollout_path;
|
||||
@@ -103,7 +103,7 @@ async fn thread_read_returns_summary_without_turns() -> Result<()> {
|
||||
/*git_info*/ None,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let read_id = mcp
|
||||
@@ -158,7 +158,7 @@ async fn thread_read_can_include_turns() -> Result<()> {
|
||||
/*git_info*/ None,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let read_id = mcp
|
||||
@@ -216,7 +216,7 @@ async fn thread_turns_list_can_page_backward_and_forward() -> Result<()> {
|
||||
append_user_message(rollout_path.as_path(), "2025-01-05T12:01:00Z", "second")?;
|
||||
append_user_message(rollout_path.as_path(), "2025-01-05T12:02:00Z", "third")?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let read_id = mcp
|
||||
@@ -305,7 +305,7 @@ async fn thread_turns_list_supports_requested_items_view() -> Result<()> {
|
||||
append_agent_message(rollout_path.as_path(), "2025-01-05T12:01:00Z", "draft")?;
|
||||
append_agent_message(rollout_path.as_path(), "2025-01-05T12:02:00Z", "final")?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let full = read_single_turn_items_view(
|
||||
@@ -384,6 +384,7 @@ async fn thread_turns_list_reads_store_history_without_rollout_path() -> Result<
|
||||
config_warnings: Vec::new(),
|
||||
session_source: SessionSource::Cli.into(),
|
||||
enable_codex_api_key_env: false,
|
||||
plugin_startup_tasks: codex_app_server::PluginStartupTasks::Start,
|
||||
initialize: InitializeParams {
|
||||
client_info: ClientInfo {
|
||||
name: "codex-app-server-tests".to_string(),
|
||||
@@ -449,6 +450,7 @@ async fn thread_read_loaded_include_turns_reads_store_history_without_rollout_pa
|
||||
config_warnings: Vec::new(),
|
||||
session_source: SessionSource::Cli.into(),
|
||||
enable_codex_api_key_env: false,
|
||||
plugin_startup_tasks: codex_app_server::PluginStartupTasks::Start,
|
||||
initialize: InitializeParams {
|
||||
client_info: ClientInfo {
|
||||
name: "codex-app-server-tests".to_string(),
|
||||
@@ -534,6 +536,7 @@ async fn thread_list_includes_store_thread_without_rollout_path() -> Result<()>
|
||||
config_warnings: Vec::new(),
|
||||
session_source: SessionSource::Cli.into(),
|
||||
enable_codex_api_key_env: false,
|
||||
plugin_startup_tasks: codex_app_server::PluginStartupTasks::Start,
|
||||
initialize: InitializeParams {
|
||||
client_info: ClientInfo {
|
||||
name: "codex-app-server-tests".to_string(),
|
||||
@@ -604,7 +607,7 @@ async fn thread_read_can_return_archived_threads_by_id() -> Result<()> {
|
||||
archived_dir.join(active_rollout_path.file_name().expect("rollout file name"));
|
||||
std::fs::rename(&active_rollout_path, &archived_rollout_path)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let read_id = mcp
|
||||
@@ -648,7 +651,7 @@ async fn thread_turns_list_rejects_cursor_when_anchor_turn_is_rolled_back() -> R
|
||||
append_user_message(rollout_path.as_path(), "2025-01-05T12:01:00Z", "second")?;
|
||||
append_user_message(rollout_path.as_path(), "2025-01-05T12:02:00Z", "third")?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let read_id = mcp
|
||||
@@ -715,7 +718,7 @@ async fn thread_read_returns_forked_from_id_for_forked_threads() -> Result<()> {
|
||||
/*git_info*/ None,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let fork_id = mcp
|
||||
@@ -755,7 +758,7 @@ async fn thread_read_loaded_thread_returns_precomputed_path_before_materializati
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -815,7 +818,7 @@ async fn thread_name_set_is_reflected_in_read_list_and_resume() -> Result<()> {
|
||||
/*git_info*/ None,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
// Set a user-facing thread title.
|
||||
@@ -961,7 +964,7 @@ async fn thread_read_include_turns_rejects_unmaterialized_loaded_thread() -> Res
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -1012,7 +1015,7 @@ async fn thread_turns_list_rejects_unmaterialized_loaded_thread() -> Result<()>
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -1066,7 +1069,7 @@ async fn thread_turns_items_list_returns_unsupported() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let read_id = mcp
|
||||
@@ -1104,7 +1107,7 @@ async fn thread_read_reports_system_error_idle_flag_after_failed_turn() -> Resul
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -1213,7 +1216,7 @@ fn append_thread_rollback(path: &Path, timestamp: &str, num_turns: u32) -> std::
|
||||
}
|
||||
|
||||
async fn read_single_turn_items_view(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
thread_id: &str,
|
||||
items_view: Option<TurnItemsView>,
|
||||
) -> anyhow::Result<codex_app_server_protocol::Turn> {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::create_apply_patch_sse_response;
|
||||
use app_test_support::create_fake_rollout;
|
||||
use app_test_support::create_fake_rollout_with_text_elements;
|
||||
@@ -143,7 +143,7 @@ async fn thread_resume_rejects_unmaterialized_thread() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
// Start a thread.
|
||||
@@ -196,7 +196,8 @@ async fn thread_goal_get_rejects_unmaterialized_thread() -> Result<()> {
|
||||
config.replace("personality = true\n", "personality = true\ngoals = true\n"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_in_process_without_managed_config(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -261,7 +262,7 @@ async fn thread_resume_tracks_thread_initialized_analytics() -> Result<()> {
|
||||
"user",
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let resume_id = mcp
|
||||
@@ -332,7 +333,7 @@ async fn thread_resume_returns_rollout_history() -> Result<()> {
|
||||
/*git_info*/ None,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let resume_id = mcp
|
||||
@@ -495,7 +496,7 @@ async fn resume_redaction_fixture(
|
||||
&conversation_id,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
if let Some(client_name) = client_name {
|
||||
let _ = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
@@ -595,7 +596,7 @@ async fn thread_resume_can_skip_turns_for_metadata_only_resume() -> Result<()> {
|
||||
/*git_info*/ None,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let resume_id = mcp
|
||||
@@ -630,7 +631,8 @@ async fn thread_resume_keeps_paused_goal_paused() -> Result<()> {
|
||||
config.replace("personality = true\n", "personality = true\ngoals = true\n"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_in_process_without_managed_config(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -734,7 +736,8 @@ async fn thread_goal_set_preserves_budget_limited_same_objective() -> Result<()>
|
||||
config.replace("personality = true\n", "personality = true\ngoals = true\n"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_in_process_without_managed_config(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -840,7 +843,8 @@ async fn thread_goal_set_edits_objective_without_resetting_usage() -> Result<()>
|
||||
/*git_info*/ None,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_in_process_without_managed_config(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let goal_id = mcp
|
||||
@@ -928,7 +932,8 @@ async fn thread_goal_clear_deletes_goal_and_notifies() -> Result<()> {
|
||||
config.replace("personality = true\n", "personality = true\ngoals = true\n"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
let mut mcp =
|
||||
AppServerTestProcess::new_in_process_without_managed_config(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -1057,7 +1062,7 @@ async fn thread_resume_emits_restored_token_usage_before_next_turn() -> Result<(
|
||||
Some("mock_provider"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let resume_id = mcp
|
||||
@@ -1110,7 +1115,7 @@ async fn thread_resume_skips_restored_token_usage_when_turns_are_excluded() -> R
|
||||
Some("mock_provider"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let first_resume_id = mcp
|
||||
@@ -1217,7 +1222,7 @@ async fn thread_resume_token_usage_replay_ignores_stale_interrupted_tail_turn()
|
||||
format!("{persisted_rollout}{appended_rollout}\n"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let resume_id = mcp
|
||||
@@ -1340,7 +1345,7 @@ async fn thread_resume_token_usage_replay_can_belong_to_interrupted_turn() -> Re
|
||||
format!("{persisted_rollout}{appended_rollout}\n"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let resume_id = mcp
|
||||
@@ -1528,7 +1533,7 @@ stream_max_retries = 0
|
||||
.mark_backfill_complete(/*last_watermark*/ None)
|
||||
.await?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let update_id = mcp
|
||||
@@ -1621,7 +1626,7 @@ async fn thread_resume_and_read_interrupt_incomplete_rollout_turn_when_thread_is
|
||||
format!("{persisted_rollout}{appended_rollout}\n"),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let resume_id = mcp
|
||||
@@ -1695,7 +1700,7 @@ async fn thread_resume_without_overrides_does_not_change_updated_at_or_mtime() -
|
||||
let rollout = setup_rollout_fixture(codex_home.path(), &server.uri())?;
|
||||
let thread_id = rollout.conversation_id.clone();
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let read_id = mcp
|
||||
@@ -1766,7 +1771,7 @@ async fn thread_resume_keeps_in_flight_turn_streaming() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut primary = McpProcess::new(codex_home.path()).await?;
|
||||
let mut primary = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
@@ -1804,7 +1809,7 @@ async fn thread_resume_keeps_in_flight_turn_streaming() -> Result<()> {
|
||||
.await??;
|
||||
primary.clear_message_buffer();
|
||||
|
||||
let mut secondary = McpProcess::new(codex_home.path()).await?;
|
||||
let mut secondary = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, secondary.initialize()).await??;
|
||||
|
||||
let turn_id = primary
|
||||
@@ -1873,7 +1878,7 @@ async fn thread_resume_rejects_history_when_thread_is_running() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut primary = McpProcess::new(codex_home.path()).await?;
|
||||
let mut primary = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
@@ -1989,7 +1994,7 @@ async fn thread_resume_uses_path_over_thread_id_when_thread_is_running() -> Resu
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut primary = McpProcess::new(codex_home.path()).await?;
|
||||
let mut primary = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
@@ -2142,7 +2147,7 @@ async fn thread_resume_rejoins_running_thread_even_with_override_mismatch() -> R
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut primary = McpProcess::new(codex_home.path()).await?;
|
||||
let mut primary = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
@@ -2250,7 +2255,7 @@ async fn thread_resume_can_skip_turns_when_thread_is_running() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut primary = McpProcess::new(codex_home.path()).await?;
|
||||
let mut primary = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
@@ -2287,7 +2292,7 @@ async fn thread_resume_can_skip_turns_when_thread_is_running() -> Result<()> {
|
||||
)
|
||||
.await??;
|
||||
|
||||
let mut secondary = McpProcess::new(codex_home.path()).await?;
|
||||
let mut secondary = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, secondary.initialize()).await??;
|
||||
|
||||
let resume_id = secondary
|
||||
@@ -2333,7 +2338,7 @@ async fn thread_resume_replays_pending_command_execution_request_approval() -> R
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut primary = McpProcess::new(codex_home.path()).await?;
|
||||
let mut primary = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
@@ -2470,7 +2475,7 @@ async fn thread_resume_replays_pending_file_change_request_approval() -> Result<
|
||||
let server = create_mock_responses_server_sequence_unchecked(responses).await;
|
||||
create_config_toml(&codex_home, &server.uri())?;
|
||||
|
||||
let mut primary = McpProcess::new(&codex_home).await?;
|
||||
let mut primary = AppServerTestProcess::new(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
@@ -2688,7 +2693,7 @@ async fn thread_resume_fails_when_required_mcp_server_fails_to_initialize() -> R
|
||||
let rollout = setup_rollout_fixture(codex_home.path(), &server.uri())?;
|
||||
create_config_toml_with_required_broken_mcp(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let resume_id = mcp
|
||||
@@ -2767,7 +2772,7 @@ async fn thread_resume_surfaces_cloud_requirements_load_errors() -> Result<()> {
|
||||
/*git_info*/ None,
|
||||
)?;
|
||||
let refresh_token_url = format!("{}/oauth/token", server.uri());
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("OPENAI_API_KEY", None),
|
||||
@@ -2817,7 +2822,7 @@ async fn thread_resume_uses_path_over_invalid_thread_id() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -2892,7 +2897,7 @@ async fn thread_resume_can_load_source_by_external_path() -> Result<()> {
|
||||
)?;
|
||||
let thread_path = rollout_path(external_home.path(), "2025-01-05T12-00-00", &thread_id);
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
let resume_id = mcp
|
||||
.send_thread_resume_request(ThreadResumeParams {
|
||||
@@ -2971,7 +2976,7 @@ async fn thread_resume_supports_history_and_overrides() -> Result<()> {
|
||||
}
|
||||
|
||||
struct RestartedThreadFixture {
|
||||
mcp: McpProcess,
|
||||
mcp: AppServerTestProcess,
|
||||
thread_id: String,
|
||||
rollout_file_path: PathBuf,
|
||||
updated_at: i64,
|
||||
@@ -2981,7 +2986,7 @@ async fn start_materialized_thread_and_restart(
|
||||
codex_home: &Path,
|
||||
seed_text: &str,
|
||||
) -> Result<RestartedThreadFixture> {
|
||||
let mut first_mcp = McpProcess::new(codex_home).await?;
|
||||
let mut first_mcp = AppServerTestProcess::new(codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, first_mcp.initialize()).await??;
|
||||
|
||||
let start_id = first_mcp
|
||||
@@ -3039,7 +3044,7 @@ async fn start_materialized_thread_and_restart(
|
||||
|
||||
drop(first_mcp);
|
||||
|
||||
let mut second_mcp = McpProcess::new(codex_home).await?;
|
||||
let mut second_mcp = AppServerTestProcess::new(codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, second_mcp.initialize()).await??;
|
||||
|
||||
Ok(RestartedThreadFixture {
|
||||
@@ -3070,7 +3075,7 @@ async fn thread_resume_accepts_personality_override() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut primary = McpProcess::new(codex_home.path()).await?;
|
||||
let mut primary = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
@@ -3107,7 +3112,7 @@ async fn thread_resume_accepts_personality_override() -> Result<()> {
|
||||
)
|
||||
.await??;
|
||||
|
||||
let mut secondary = McpProcess::new(codex_home.path()).await?;
|
||||
let mut secondary = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, secondary.initialize()).await??;
|
||||
|
||||
let resume_id = secondary
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
use app_test_support::to_response;
|
||||
@@ -35,7 +35,7 @@ async fn thread_rollback_drops_last_turns_and_persists_to_rollout() -> Result<()
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
// Start a thread.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
use app_test_support::create_mock_responses_server_sequence;
|
||||
use app_test_support::create_shell_command_sse_response;
|
||||
@@ -59,7 +59,7 @@ async fn thread_shell_command_history_responses_exclude_persisted_command_execut
|
||||
&BTreeMap::default(),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.as_path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.as_path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -211,7 +211,7 @@ async fn thread_shell_command_uses_existing_active_turn() -> Result<()> {
|
||||
&BTreeMap::default(),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.as_path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.as_path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -365,7 +365,7 @@ fn current_shell_output_command(text: &str) -> Result<(String, String)> {
|
||||
}
|
||||
|
||||
async fn wait_for_command_execution_started(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
expected_id: Option<&str>,
|
||||
) -> Result<ItemStartedNotification> {
|
||||
loop {
|
||||
@@ -387,7 +387,7 @@ async fn wait_for_command_execution_started(
|
||||
}
|
||||
|
||||
async fn wait_for_command_execution_started_by_source(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
expected_source: CommandExecutionSource,
|
||||
) -> Result<ItemStartedNotification> {
|
||||
loop {
|
||||
@@ -402,7 +402,7 @@ async fn wait_for_command_execution_started_by_source(
|
||||
}
|
||||
|
||||
async fn wait_for_command_execution_completed(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
expected_id: Option<&str>,
|
||||
) -> Result<ItemCompletedNotification> {
|
||||
loop {
|
||||
@@ -424,7 +424,7 @@ async fn wait_for_command_execution_completed(
|
||||
}
|
||||
|
||||
async fn wait_for_command_execution_output_delta(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
item_id: &str,
|
||||
) -> Result<CommandExecutionOutputDeltaNotification> {
|
||||
loop {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::PathBufExt;
|
||||
use app_test_support::create_mock_responses_server_repeating_assistant;
|
||||
use app_test_support::to_response;
|
||||
@@ -57,7 +57,7 @@ async fn thread_start_deprecates_persist_extended_history_true() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml_without_approval_policy(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let req_id = mcp
|
||||
@@ -100,7 +100,7 @@ async fn thread_start_creates_thread_and_emits_started() -> Result<()> {
|
||||
create_config_toml_without_approval_policy(codex_home.path(), &server.uri())?;
|
||||
|
||||
// Start server and initialize.
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
// Start a v2 thread with an explicit model override.
|
||||
@@ -243,7 +243,7 @@ async fn thread_start_rejects_unknown_environment_as_invalid_request() -> Result
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml_without_approval_policy(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -280,7 +280,7 @@ async fn thread_start_response_includes_loaded_instruction_sources() -> Result<(
|
||||
let project_agents_path = workspace.path().join("AGENTS.md");
|
||||
std::fs::write(&project_agents_path, "project instructions")?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -336,7 +336,7 @@ async fn thread_start_tracks_thread_initialized_analytics() -> Result<()> {
|
||||
create_config_toml_with_chatgpt_base_url(codex_home.path(), &server.uri(), &server.uri())?;
|
||||
mount_analytics_capture(&server, codex_home.path()).await?;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let req_id = mcp
|
||||
@@ -377,7 +377,7 @@ model_reasoning_effort = "high"
|
||||
)?;
|
||||
set_project_trust_level(codex_home.path(), workspace.path(), TrustLevel::Trusted)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let req_id = mcp
|
||||
@@ -407,7 +407,7 @@ async fn thread_start_accepts_arbitrary_service_tier_id() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml_without_approval_policy(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let service_tier_id = "experimental-tier-id".to_string();
|
||||
@@ -436,7 +436,7 @@ async fn thread_start_accepts_metrics_service_name() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml_without_approval_policy(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let req_id = mcp
|
||||
@@ -463,7 +463,7 @@ async fn thread_start_ephemeral_remains_pathless() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml_without_approval_policy(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let req_id = mcp
|
||||
@@ -509,7 +509,7 @@ async fn thread_start_fails_when_required_mcp_server_fails_to_initialize() -> Re
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml_with_required_broken_mcp(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let req_id = mcp
|
||||
@@ -545,7 +545,7 @@ async fn thread_start_emits_mcp_server_status_updated_notifications() -> Result<
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml_with_optional_broken_mcp(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let req_id = mcp
|
||||
@@ -675,7 +675,7 @@ async fn thread_start_surfaces_cloud_requirements_load_errors() -> Result<()> {
|
||||
)?;
|
||||
|
||||
let refresh_token_url = format!("{}/oauth/token", server.uri());
|
||||
let mut mcp = McpProcess::new_with_env(
|
||||
let mut mcp = AppServerTestProcess::new_with_env(
|
||||
codex_home.path(),
|
||||
&[
|
||||
("OPENAI_API_KEY", None),
|
||||
@@ -735,7 +735,7 @@ model_reasoning_effort = "high"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let first_request = mcp
|
||||
@@ -795,7 +795,7 @@ async fn thread_start_with_nested_git_cwd_trusts_repo_root() -> Result<()> {
|
||||
let nested = repo_root.path().join("nested/project");
|
||||
std::fs::create_dir_all(&nested)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -833,7 +833,7 @@ async fn thread_start_with_read_only_sandbox_does_not_persist_project_trust() ->
|
||||
|
||||
let workspace = TempDir::new()?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -871,7 +871,7 @@ async fn thread_start_preserves_untrusted_project_trust() -> Result<()> {
|
||||
std::fs::write(&config_path, config_toml.to_string())?;
|
||||
let config_before = std::fs::read_to_string(&config_path)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -912,7 +912,7 @@ model_reasoning_effort = "high"
|
||||
set_project_trust_level(codex_home.path(), workspace.path(), TrustLevel::Trusted)?;
|
||||
let config_before = std::fs::read_to_string(codex_home.path().join("config.toml"))?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
use app_test_support::create_mock_responses_server_sequence;
|
||||
use app_test_support::to_response;
|
||||
@@ -29,7 +29,8 @@ async fn thread_status_changed_emits_runtime_updates() -> Result<()> {
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp =
|
||||
McpProcess::new_with_env(codex_home.path(), &[("RUST_LOG", Some("info"))]).await?;
|
||||
AppServerTestProcess::new_with_env(codex_home.path(), &[("RUST_LOG", Some("info"))])
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_start_id = mcp
|
||||
@@ -134,7 +135,7 @@ async fn thread_status_changed_can_be_opted_out() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence(responses).await;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
let message = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.initialize_with_capabilities(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_mock_responses_server_repeating_assistant;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server::in_process;
|
||||
@@ -60,7 +60,7 @@ async fn thread_unarchive_moves_rollout_back_into_sessions_directory() -> Result
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -254,6 +254,7 @@ async fn thread_unarchive_preserves_pathless_store_metadata() -> Result<()> {
|
||||
config_warnings: Vec::new(),
|
||||
session_source: SessionSource::Cli,
|
||||
enable_codex_api_key_env: false,
|
||||
plugin_startup_tasks: codex_app_server::PluginStartupTasks::Start,
|
||||
initialize: InitializeParams {
|
||||
client_info: ClientInfo {
|
||||
name: "codex-app-server-tests".to_string(),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_mock_responses_server_repeating_assistant;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::DynamicToolCallOutputContentItem;
|
||||
@@ -41,7 +41,7 @@ async fn thread_unsubscribe_keeps_thread_loaded_until_idle_timeout() -> Result<(
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_id = start_thread(&mut mcp).await?;
|
||||
@@ -120,7 +120,7 @@ async fn thread_unsubscribe_during_turn_keeps_turn_running() -> Result<()> {
|
||||
let final_response_completed = completions.remove(0);
|
||||
create_config_toml(&codex_home, server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -252,7 +252,7 @@ async fn thread_unsubscribe_preserves_cached_status_before_idle_unload() -> Resu
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_id = start_thread(&mut mcp).await?;
|
||||
@@ -337,7 +337,7 @@ async fn thread_unsubscribe_reports_not_subscribed_before_idle_unload() -> Resul
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_in_process(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_id = start_thread(&mut mcp).await?;
|
||||
@@ -376,7 +376,7 @@ async fn thread_unsubscribe_reports_not_subscribed_before_idle_unload() -> Resul
|
||||
}
|
||||
|
||||
async fn wait_for_dynamic_tool_started(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
call_id: &str,
|
||||
) -> Result<ItemStartedNotification> {
|
||||
loop {
|
||||
@@ -416,7 +416,7 @@ stream_max_retries = 0
|
||||
)
|
||||
}
|
||||
|
||||
async fn start_thread(mcp: &mut McpProcess) -> Result<String> {
|
||||
async fn start_thread(mcp: &mut AppServerTestProcess) -> Result<String> {
|
||||
let req_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#![cfg(unix)]
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
use app_test_support::create_mock_responses_server_sequence;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
@@ -57,7 +57,7 @@ async fn turn_interrupt_aborts_running_turn() -> Result<()> {
|
||||
.await;
|
||||
create_config_toml(&codex_home, &server.uri(), "never", "workspace-write")?;
|
||||
|
||||
let mut mcp = McpProcess::new(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
// Start a v2 thread and capture its id.
|
||||
@@ -140,7 +140,7 @@ async fn turn_interrupt_rejects_completed_turn() -> Result<()> {
|
||||
.await;
|
||||
create_config_toml(&codex_home, &server.uri(), "never", "workspace-write")?;
|
||||
|
||||
let mut mcp = McpProcess::new(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -234,7 +234,7 @@ async fn turn_interrupt_resolves_pending_command_approval_request() -> Result<()
|
||||
.await;
|
||||
create_config_toml(&codex_home, &server.uri(), "untrusted", "read-only")?;
|
||||
|
||||
let mut mcp = McpProcess::new(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::DEFAULT_CLIENT_NAME;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::create_apply_patch_sse_response;
|
||||
use app_test_support::create_exec_command_sse_response;
|
||||
use app_test_support::create_fake_rollout;
|
||||
@@ -104,7 +104,7 @@ async fn turn_start_sends_originator_header() -> Result<()> {
|
||||
&BTreeMap::from([(Feature::Personality, true)]),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.initialize_with_client_info(ClientInfo {
|
||||
@@ -180,7 +180,7 @@ async fn turn_start_emits_user_message_item_with_text_elements() -> Result<()> {
|
||||
&BTreeMap::from([(Feature::Personality, true)]),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -291,7 +291,7 @@ async fn turn_start_emits_thread_scoped_warning_notification_for_trimmed_skills(
|
||||
write_test_skill(codex_home.path(), "alpha-skill")?;
|
||||
write_test_skill(codex_home.path(), "beta-skill")?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -383,7 +383,7 @@ async fn turn_start_sends_service_tier_id_to_model_request() -> Result<()> {
|
||||
.expect("bundled model catalog should include a picker model with service tiers");
|
||||
let service_tier_id = service_tier_model.service_tiers[0].id.clone();
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -447,7 +447,7 @@ async fn thread_start_omits_empty_instruction_overrides_from_model_request() ->
|
||||
&BTreeMap::default(),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -532,7 +532,7 @@ async fn turn_start_tracks_turn_event_analytics() -> Result<()> {
|
||||
)?;
|
||||
mount_analytics_capture(&server, codex_home.path()).await?;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new_without_managed_config(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -619,7 +619,7 @@ async fn turn_start_accepts_text_at_limit_with_mention_item() -> Result<()> {
|
||||
&BTreeMap::from([(Feature::Personality, true)]),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -678,7 +678,7 @@ async fn turn_start_rejects_combined_oversized_text_input() -> Result<()> {
|
||||
&BTreeMap::from([(Feature::Personality, true)]),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -757,7 +757,7 @@ async fn turn_start_rejects_invalid_permission_selection_before_starting_turn()
|
||||
"sandbox_mode = \"read-only\"\n",
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -823,7 +823,7 @@ async fn turn_start_rejects_unknown_environment_before_starting_turn() -> Result
|
||||
&BTreeMap::default(),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -894,7 +894,7 @@ async fn turn_start_emits_notifications_and_accepts_model_override() -> Result<(
|
||||
&BTreeMap::from([(Feature::Personality, true)]),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
// Start a thread (v2) and capture its id.
|
||||
@@ -1037,7 +1037,7 @@ async fn turn_start_accepts_collaboration_mode_override_v2() -> Result<()> {
|
||||
&BTreeMap::default(),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -1122,7 +1122,7 @@ async fn turn_start_uses_thread_feature_overrides_for_request_user_input_tool_de
|
||||
&BTreeMap::default(),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -1206,7 +1206,7 @@ async fn turn_start_accepts_personality_override_v2() -> Result<()> {
|
||||
&BTreeMap::from([(Feature::Personality, true)]),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -1287,7 +1287,7 @@ async fn turn_start_change_personality_mid_thread_v2() -> Result<()> {
|
||||
&BTreeMap::from([(Feature::Personality, true)]),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -1401,7 +1401,7 @@ async fn turn_start_uses_migrated_pragmatic_personality_without_override_v2() ->
|
||||
/*git_info*/ None,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let persisted_toml: ConfigToml = toml::from_str(&std::fs::read_to_string(
|
||||
@@ -1482,7 +1482,7 @@ async fn turn_start_accepts_local_image_input() -> Result<()> {
|
||||
&BTreeMap::default(),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -1567,7 +1567,7 @@ async fn turn_start_exec_approval_toggle_v2() -> Result<()> {
|
||||
&BTreeMap::default(),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.as_path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.as_path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
// thread/start
|
||||
@@ -1710,7 +1710,7 @@ async fn turn_start_exec_approval_decline_v2() -> Result<()> {
|
||||
&BTreeMap::default(),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.as_path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.as_path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -1862,7 +1862,7 @@ async fn turn_start_updates_sandbox_and_cwd_between_turns_v2() -> Result<()> {
|
||||
&BTreeMap::default(),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
// thread/start
|
||||
@@ -2009,7 +2009,7 @@ url = "ws://127.0.0.1:1"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
for case in [
|
||||
@@ -2052,7 +2052,7 @@ struct EnvironmentSelectionCase {
|
||||
}
|
||||
|
||||
async fn run_environment_selection_case(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut AppServerTestProcess,
|
||||
workspace: &Path,
|
||||
case: EnvironmentSelectionCase,
|
||||
) -> Result<()> {
|
||||
@@ -2169,7 +2169,7 @@ async fn turn_start_file_change_approval_v2() -> Result<()> {
|
||||
&BTreeMap::default(),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_req = mcp
|
||||
@@ -2359,7 +2359,7 @@ async fn turn_start_does_not_stream_apply_patch_change_updates_without_feature_v
|
||||
let server = create_mock_responses_server_sequence(responses).await;
|
||||
create_config_toml(&codex_home, &server.uri(), "never", &BTreeMap::default())?;
|
||||
|
||||
let mut mcp = McpProcess::new(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_req = mcp
|
||||
@@ -2483,7 +2483,7 @@ async fn turn_start_streams_apply_patch_change_updates_v2() -> Result<()> {
|
||||
]),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_req = mcp
|
||||
@@ -2609,7 +2609,7 @@ async fn turn_start_emits_spawn_agent_item_with_model_metadata_v2() -> Result<()
|
||||
&BTreeMap::from([(Feature::Collab, true)]),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -2823,7 +2823,7 @@ config_file = "./custom-role.toml"
|
||||
),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -2966,7 +2966,7 @@ async fn turn_start_file_change_approval_accept_for_session_persists_v2() -> Res
|
||||
&BTreeMap::default(),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_req = mcp
|
||||
@@ -3137,7 +3137,7 @@ async fn turn_start_file_change_approval_decline_v2() -> Result<()> {
|
||||
&BTreeMap::default(),
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_req = mcp
|
||||
@@ -3283,7 +3283,7 @@ async fn command_execution_notifications_include_process_id() -> Result<()> {
|
||||
"danger-full-access",
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
@@ -3416,7 +3416,7 @@ async fn turn_start_with_elevated_override_does_not_persist_project_trust() -> R
|
||||
|
||||
let workspace = TempDir::new()?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_request = mcp
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
// network access are required the first time the artifact is fetched.
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
use app_test_support::create_mock_responses_server_sequence;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
@@ -738,9 +738,12 @@ async fn turn_start_shell_zsh_fork_subcommand_decline_marks_parent_declined_v2()
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_zsh_test_mcp_process(codex_home: &Path, zdotdir: &Path) -> Result<McpProcess> {
|
||||
async fn create_zsh_test_mcp_process(
|
||||
codex_home: &Path,
|
||||
zdotdir: &Path,
|
||||
) -> Result<AppServerTestProcess> {
|
||||
let zdotdir = zdotdir.to_string_lossy().into_owned();
|
||||
McpProcess::new_with_env(codex_home, &[("ZDOTDIR", Some(zdotdir.as_str()))]).await
|
||||
AppServerTestProcess::new_with_env(codex_home, &[("ZDOTDIR", Some(zdotdir.as_str()))]).await
|
||||
}
|
||||
|
||||
fn create_config_toml(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#![cfg(unix)]
|
||||
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_mock_responses_server_sequence;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
use app_test_support::create_shell_command_sse_response;
|
||||
@@ -43,7 +43,7 @@ async fn turn_steer_requires_active_turn() -> Result<()> {
|
||||
)?;
|
||||
mount_analytics_capture(&server, &codex_home).await?;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new_without_managed_config(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -127,7 +127,7 @@ async fn turn_steer_rejects_oversized_text_input() -> Result<()> {
|
||||
)?;
|
||||
mount_analytics_capture(&server, &codex_home).await?;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new_without_managed_config(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -236,7 +236,7 @@ async fn turn_steer_returns_active_turn_id() -> Result<()> {
|
||||
)?;
|
||||
mount_analytics_capture(&server, &codex_home).await?;
|
||||
|
||||
let mut mcp = McpProcess::new_without_managed_config(&codex_home).await?;
|
||||
let mut mcp = AppServerTestProcess::new_without_managed_config(&codex_home).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::AppServerTestProcess;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_mock_responses_config_toml;
|
||||
@@ -31,7 +31,7 @@ async fn windows_sandbox_setup_start_emits_completion_notification() -> Result<(
|
||||
"mock_provider",
|
||||
"compact prompt",
|
||||
)?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
@@ -66,7 +66,7 @@ async fn windows_sandbox_setup_start_emits_completion_notification() -> Result<(
|
||||
#[tokio::test]
|
||||
async fn windows_sandbox_setup_start_rejects_relative_cwd() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
let mut mcp = AppServerTestProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
|
||||
Reference in New Issue
Block a user