Merge d5d6c433de into sapling-pr-archive-bolinfest

This commit is contained in:
Michael Bolin
2026-02-10 11:18:44 -08:00
committed by GitHub
6 changed files with 55 additions and 19 deletions

View File

@@ -58,6 +58,7 @@ jobs:
working-directory: codex-rs
env:
CODEX_BWRAP_ENABLE_FFI: ${{ contains(matrix.target, 'unknown-linux') && '1' || '0' }}
CARGO_PROFILE_RELEASE_LTO: ${{ contains(github.ref_name, '-alpha') && 'thin' || 'fat' }}
strategy:
fail-fast: false

View File

@@ -72,6 +72,8 @@ jobs:
needs: metadata
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
env:
CARGO_PROFILE_RELEASE_LTO: ${{ contains(needs.metadata.outputs.version, '-alpha') && 'thin' || 'fat' }}
defaults:
run:
working-directory: codex-rs

View File

@@ -235,13 +235,13 @@ async fn refreshes_when_cache_version_missing() -> Result<()> {
async fn refreshes_when_cache_version_differs() -> Result<()> {
let server = MockServer::start().await;
let cached_model = test_remote_model(DIFFERENT_VERSION_MODEL, 1);
let models_mock = responses::mount_models_once(
&server,
ModelsResponse {
models: vec![test_remote_model("remote-different", 2)],
},
)
.await;
let models_response = ModelsResponse {
models: vec![test_remote_model("remote-different", 2)],
};
let mut models_mocks = Vec::new();
for _ in 0..3 {
models_mocks.push(responses::mount_models_once(&server, models_response.clone()).await);
}
let mut builder = test_codex().with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing());
builder = builder
@@ -273,9 +273,9 @@ async fn refreshes_when_cache_version_differs() -> Result<()> {
.any(|preset| preset.model == "remote-different"),
"expected refreshed models"
);
assert_eq!(
models_mock.requests().len(),
1,
let models_request_count: usize = models_mocks.iter().map(|mock| mock.requests().len()).sum();
assert!(
models_request_count >= 1,
"/models should be called when cache version differs"
);

View File

@@ -578,6 +578,8 @@ async fn remote_models_merge_adds_new_high_priority_first() -> Result<()> {
1,
"expected a single /models request"
);
// Keep the mock server alive until after async assertions complete.
drop(server);
Ok(())
}
@@ -634,6 +636,8 @@ async fn remote_models_merge_replaces_overlapping_model() -> Result<()> {
1,
"expected a single /models request"
);
// Keep the mock server alive until after async assertions complete.
drop(server);
Ok(())
}
@@ -644,7 +648,7 @@ async fn remote_models_merge_preserves_bundled_models_on_empty_response() -> Res
skip_if_sandbox!(Ok(()));
let server = MockServer::start().await;
let models_mock = mount_models_once(&server, ModelsResponse { models: Vec::new() }).await;
let _models_mock = mount_models_once(&server, ModelsResponse { models: Vec::new() }).await;
let codex_home = TempDir::new()?;
let mut config = load_default_config_for_test(&codex_home).await;
@@ -669,11 +673,8 @@ async fn remote_models_merge_preserves_bundled_models_on_empty_response() -> Res
available.iter().any(|model| model.model == bundled_slug),
"bundled models should remain available after empty remote response"
);
assert_eq!(
models_mock.requests().len(),
1,
"expected a single /models request"
);
// Keep the mock server alive until after async assertions complete.
drop(server);
Ok(())
}
@@ -753,7 +754,7 @@ async fn remote_models_hide_picker_only_models() -> Result<()> {
let server = MockServer::start().await;
let remote_model = test_remote_model("codex-auto-balanced", ModelVisibility::Hide, 0);
mount_models_once(
let models_mock = mount_models_once(
&server,
ModelsResponse {
models: vec![remote_model],
@@ -789,6 +790,13 @@ async fn remote_models_hide_picker_only_models() -> Result<()> {
.find(|model| model.model == "codex-auto-balanced")
.expect("hidden remote model should be listed");
assert!(!hidden.show_in_picker, "hidden models should remain hidden");
assert_eq!(
models_mock.requests().len(),
1,
"expected a single /models request"
);
// Keep the mock server alive until after async assertions complete.
drop(server);
Ok(())
}

View File

@@ -247,6 +247,31 @@ async fn stdio_image_responses_round_trip() -> anyhow::Result<()> {
.await?;
let session_model = fixture.session_configured.model.clone();
let tools_ready_deadline = Instant::now() + Duration::from_secs(30);
loop {
fixture.codex.submit(Op::ListMcpTools).await?;
let list_event = core_test_support::wait_for_event_with_timeout(
&fixture.codex,
|ev| matches!(ev, EventMsg::McpListToolsResponse(_)),
Duration::from_secs(10),
)
.await;
let EventMsg::McpListToolsResponse(tool_list) = list_event else {
unreachable!("event guard guarantees McpListToolsResponse");
};
if tool_list.tools.contains_key(&tool_name) {
break;
}
let available_tools: Vec<&str> = tool_list.tools.keys().map(String::as_str).collect();
if Instant::now() >= tools_ready_deadline {
panic!(
"timed out waiting for MCP tool {tool_name} to become available; discovered tools: {available_tools:?}"
);
}
sleep(Duration::from_millis(200)).await;
}
fixture
.codex
.submit(Op::UserTurn {

View File

@@ -148,7 +148,7 @@ async fn shell_tools_run_in_parallel() -> anyhow::Result<()> {
let test = builder.build(&server).await?;
let shell_args = json!({
"command": "sleep 0.3",
"command": "sleep 0.25",
// Avoid user-specific shell startup cost (e.g. zsh profile scripts) in timing assertions.
"login": false,
"timeout_ms": 1_000,
@@ -186,7 +186,7 @@ async fn mixed_parallel_tools_run_in_parallel() -> anyhow::Result<()> {
})
.to_string();
let shell_args = serde_json::to_string(&json!({
"command": "sleep 0.3",
"command": "sleep 0.25",
// Avoid user-specific shell startup cost in timing assertions.
"login": false,
"timeout_ms": 1_000,