codex: fix CI failure on PR #32000

This commit is contained in:
Adam Perry
2026-07-10 04:23:43 +00:00
parent 565478e70a
commit 1e03ae6592
11 changed files with 44 additions and 19 deletions
+1 -1
View File
@@ -512,7 +512,7 @@ impl AnalyticsEventsClient {
&self,
completed_at_ms: u64,
request_id: RequestId,
response: RequestPermissionsResponse,
response: RequestPermissionsResponse<String>,
) {
self.record_fact(AnalyticsFact::EffectivePermissionsApprovalResponse {
completed_at_ms,
+1 -1
View File
@@ -483,7 +483,7 @@ pub(crate) enum AnalyticsFact {
EffectivePermissionsApprovalResponse {
completed_at_ms: u64,
request_id: RequestId,
response: Box<RequestPermissionsResponse>,
response: Box<RequestPermissionsResponse<String>>,
},
ServerRequestAborted {
completed_at_ms: u64,
+2 -2
View File
@@ -1118,7 +1118,7 @@ impl AnalyticsReducer {
&mut self,
completed_at_ms: u64,
request_id: RequestId,
response: CoreRequestPermissionsResponse,
response: CoreRequestPermissionsResponse<String>,
out: &mut Vec<TrackEventRequest>,
) {
let Some(pending_review) = self.pending_reviews.remove(&request_id) else {
@@ -2229,7 +2229,7 @@ fn file_change_review_result(
}
fn effective_permissions_review_result(
response: &CoreRequestPermissionsResponse,
response: &CoreRequestPermissionsResponse<String>,
) -> (ReviewStatus, ReviewResolution) {
if response.permissions.is_empty() {
return (ReviewStatus::Denied, ReviewResolution::None);
@@ -540,10 +540,7 @@ pub(crate) async fn apply_bespoke_event_handling(
item_id: item_id.clone(),
started_at_ms: event.started_at_ms,
reason: event.reason.clone(),
grant_root: event
.grant_root
.as_deref()
.map(LegacyAppPathString::from_path),
grant_root: event.grant_root.clone(),
};
let (pending_request_id, rx) = outgoing
.send_request(ServerRequestPayload::FileChangeRequestApproval(params))
+3 -2
View File
@@ -18,6 +18,7 @@ use codex_otel::span_w3c_trace_context;
use codex_protocol::ThreadId;
use codex_protocol::protocol::W3cTraceContext;
use codex_protocol::request_permissions::RequestPermissionsResponse;
use codex_utils_path_uri::PathUri;
use tokio::sync::Mutex;
use tokio::sync::mpsc;
use tokio::sync::oneshot;
@@ -146,14 +147,14 @@ impl ThreadScopedOutgoingMessageSender {
pub(crate) fn track_effective_permissions_approval_response(
&self,
request_id: RequestId,
response: RequestPermissionsResponse,
response: RequestPermissionsResponse<PathUri>,
) {
self.outgoing
.analytics_events_client
.track_effective_permissions_approval_response(
now_unix_timestamp_ms(),
request_id,
response,
response.map_paths(|path| path.inferred_native_path_string()),
);
}
@@ -1,5 +1,7 @@
use super::*;
use codex_core::config::permission_profile_catalog;
use codex_utils_path_uri::LegacyAppPathString;
use codex_utils_path_uri::PathConvention;
use futures::StreamExt;
#[derive(Clone)]
@@ -15,6 +17,21 @@ pub(crate) struct CatalogRequestProcessor {
const SKILLS_LIST_CWD_CONCURRENCY: usize = 5;
fn localize_catalog_cwd(cwd: &LegacyAppPathString) -> Result<AbsolutePathBuf, String> {
match cwd.to_host_abs_path() {
Ok(cwd) => return Ok(cwd),
Err(host_err) if cwd.infer_absolute_path_convention() == Some(PathConvention::native()) => {
return Err(host_err.to_string());
}
Err(_) => {}
}
if let Some(convention) = cwd.infer_absolute_path_convention() {
let path_uri = cwd.to_path_uri(convention).map_err(|err| err.to_string())?;
return Err(format!("invalid cwd: foreign path URI {path_uri}"));
}
AbsolutePathBuf::relative_to_current_dir(cwd.as_str()).map_err(|err| err.to_string())
}
fn skills_to_info(
skills: &[codex_core::skills::SkillMetadata],
disabled_paths: &HashSet<AbsolutePathBuf>,
@@ -421,9 +438,10 @@ impl CatalogRequestProcessor {
let PermissionProfileListParams { cursor, limit, cwd } = params;
let config_layer_stack = match cwd {
Some(cwd) => {
let cwd = PathBuf::from(cwd);
let cwd = localize_catalog_cwd(&cwd)
.map_err(|err| invalid_request(format!("invalid cwd: {err}")))?;
let (_, config_layer_stack) = self
.resolve_cwd_config(&cwd)
.resolve_cwd_config(cwd.as_path())
.await
.map_err(|err| internal_error(format!("failed to reload config: {err}")))?;
config_layer_stack
@@ -233,7 +233,11 @@ impl CommandExecRequestProcessor {
config.managed_network_requirements_enabled(),
config.effective_workspace_roots(),
)
} else if let Some(policy) = sandbox_policy.map(|policy| policy.to_core()) {
} else if let Some(policy) = sandbox_policy
.map(|policy| policy.try_to_core())
.transpose()
.map_err(|err| invalid_request(format!("invalid sandbox policy: {err}")))?
{
self.config
.permissions
.can_set_legacy_sandbox_policy(&policy, &sandbox_cwd)
@@ -660,7 +660,10 @@ impl TurnRequestProcessor {
approval_policy.map(codex_app_server_protocol::AskForApproval::to_core);
let approvals_reviewer =
approvals_reviewer.map(codex_app_server_protocol::ApprovalsReviewer::to_core);
let sandbox_policy = sandbox_policy.map(|policy| policy.to_core());
let sandbox_policy = sandbox_policy
.map(|policy| policy.try_to_core())
.transpose()
.map_err(|err| invalid_request(format!("invalid sandbox policy: {err}")))?;
let (permission_profile, active_permission_profile, profile_workspace_roots) =
if let Some(permissions) = permissions {
let Some(snapshot) = snapshot.as_ref() else {
@@ -13,6 +13,7 @@ use codex_protocol::config_types::TrustLevel;
use codex_protocol::models::BUILT_IN_PERMISSION_PROFILE_DANGER_FULL_ACCESS;
use codex_protocol::models::BUILT_IN_PERMISSION_PROFILE_READ_ONLY;
use codex_protocol::models::BUILT_IN_PERMISSION_PROFILE_WORKSPACE;
use codex_utils_path_uri::LegacyAppPathString;
use pretty_assertions::assert_eq;
use tempfile::TempDir;
use tokio::time::timeout;
@@ -128,7 +129,7 @@ description = "Project-scoped profile."
.send_permission_profile_list_request(PermissionProfileListParams {
cursor: None,
limit: Some(3),
cwd: Some(workspace.path().to_string_lossy().into_owned()),
cwd: Some(LegacyAppPathString::from_path(workspace.path())),
})
.await?;
let first = read_response::<PermissionProfileListResponse>(&mut mcp, first_request_id).await?;
@@ -160,7 +161,7 @@ description = "Project-scoped profile."
.send_permission_profile_list_request(PermissionProfileListParams {
cursor: first.next_cursor,
limit: Some(3),
cwd: Some(workspace.path().to_string_lossy().into_owned()),
cwd: Some(LegacyAppPathString::from_path(workspace.path())),
})
.await?;
let second =
@@ -209,7 +210,7 @@ description = "Project-scoped profile."
.send_permission_profile_list_request(PermissionProfileListParams {
cursor: None,
limit: None,
cwd: Some(workspace.path().to_string_lossy().into_owned()),
cwd: Some(LegacyAppPathString::from_path(workspace.path())),
})
.await?;
let actual = read_response::<PermissionProfileListResponse>(&mut mcp, request_id).await?;
@@ -87,7 +87,7 @@ async fn request_permissions_round_trip() -> Result<()> {
assert_eq!(params.thread_id, thread.id);
assert_eq!(params.turn_id, turn.id);
assert_eq!(params.item_id, "call1");
assert!(params.cwd.as_path().is_absolute());
assert!(params.cwd.to_host_abs_path()?.is_absolute());
assert_eq!(params.reason, Some("Select a workspace root".to_string()));
let requested_file_system = params
.permissions
@@ -78,6 +78,7 @@ use codex_protocol::openai_models::ReasoningEffort;
use codex_protocol::protocol::MULTI_AGENT_MODE_OPEN_TAG;
use codex_protocol::user_input::MAX_USER_INPUT_TEXT_CHARS;
use codex_utils_absolute_path::test_support::PathExt;
use codex_utils_path_uri::LegacyAppPathString;
use core_test_support::responses;
use core_test_support::skip_if_no_network;
use pretty_assertions::assert_eq;
@@ -2599,7 +2600,7 @@ async fn turn_start_updates_sandbox_and_cwd_between_turns_v2() -> Result<()> {
approval_policy: Some(codex_app_server_protocol::AskForApproval::Never),
approvals_reviewer: None,
sandbox_policy: Some(codex_app_server_protocol::SandboxPolicy::WorkspaceWrite {
writable_roots: vec![first_cwd.try_into()?],
writable_roots: vec![LegacyAppPathString::from_path(&first_cwd)],
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,