app-server: use permission ids and runtime workspace roots

This commit is contained in:
Michael Bolin
2026-05-14 17:17:40 -07:00
parent 149b0e978d
commit 31f2bc6511
57 changed files with 802 additions and 607 deletions
@@ -661,6 +661,7 @@ mod tests {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: next_cwd.clone().abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: None,
message_history: None,
+8
View File
@@ -3689,6 +3689,7 @@ async fn render_clear_ui_header_after_long_transcript_for_snapshot() -> String {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/tmp/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::High),
message_history: None,
@@ -3937,6 +3938,7 @@ fn test_thread_session(thread_id: ThreadId, cwd: PathBuf) -> ThreadSessionState
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: cwd.abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: None,
message_history: None,
@@ -4512,6 +4514,7 @@ async fn backtrack_selection_with_duplicate_history_targets_unique_turn() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: None,
message_history: None,
@@ -4575,6 +4578,7 @@ async fn backtrack_selection_with_duplicate_history_targets_unique_turn() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: None,
message_history: None,
@@ -4667,6 +4671,7 @@ async fn backtrack_resubmit_preserves_data_image_urls_in_user_turn() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: None,
message_history: None,
@@ -4902,6 +4907,7 @@ async fn refreshed_snapshot_session_persists_resumed_turns() {
)];
let resumed_session = ThreadSessionState {
cwd: test_path_buf("/tmp/refreshed").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
..initial_session.clone()
};
@@ -5066,6 +5072,7 @@ async fn new_session_requests_shutdown_for_previous_conversation() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: None,
message_history: None,
@@ -5187,6 +5194,7 @@ async fn clear_only_ui_reset_preserves_chat_session_state() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/tmp/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: None,
message_history: None,
+1
View File
@@ -352,6 +352,7 @@ mod tests {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: cwd.abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: None,
message_history: None,
@@ -73,6 +73,7 @@ impl App {
permission_profile: permission_profile.clone(),
active_permission_profile: active_permission_profile.clone(),
cwd: thread.cwd.clone(),
runtime_workspace_roots: self.config.workspace_roots.clone(),
instruction_source_paths: Vec::new(),
reasoning_effort: self.chat_widget.current_reasoning_effort(),
message_history: None,
@@ -150,6 +151,7 @@ mod tests {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: cwd.abs(),
runtime_workspace_roots: vec![cwd.abs()],
instruction_source_paths: Vec::new(),
reasoning_effort: None,
message_history: None,
+94 -45
View File
@@ -34,7 +34,6 @@ use codex_app_server_protocol::MemoryResetResponse;
use codex_app_server_protocol::Model as ApiModel;
use codex_app_server_protocol::ModelListParams;
use codex_app_server_protocol::ModelListResponse;
use codex_app_server_protocol::PermissionProfileModificationParams;
use codex_app_server_protocol::PermissionProfileSelectionParams;
use codex_app_server_protocol::RateLimitSnapshot;
use codex_app_server_protocol::RequestId;
@@ -577,6 +576,12 @@ impl AppServerSession {
responsesapi_client_metadata: None,
environments: None,
cwd: Some(cwd),
runtime_workspace_roots: Some(
workspace_roots
.iter()
.map(AbsolutePathBuf::to_path_buf)
.collect(),
),
approval_policy: Some(approval_policy),
approvals_reviewer: Some(approvals_reviewer.into()),
sandbox_policy,
@@ -1175,34 +1180,22 @@ fn sandbox_mode_from_permission_profile(
fn permissions_selection_from_active_profile(
active: ActivePermissionProfile,
cwd: &std::path::Path,
workspace_roots: &[AbsolutePathBuf],
) -> PermissionProfileSelectionParams {
let modifications = workspace_roots
.iter()
.filter(|root| root.as_path() != cwd)
.cloned()
.map(|path| PermissionProfileModificationParams::AdditionalWritableRoot { path })
.collect::<Vec<_>>();
PermissionProfileSelectionParams::Profile {
id: active.id,
modifications: (!modifications.is_empty()).then_some(modifications),
}
PermissionProfileSelectionParams::new(active.id)
}
fn turn_permissions_overrides(
permission_profile: &PermissionProfile,
active_permission_profile: Option<ActivePermissionProfile>,
cwd: &std::path::Path,
workspace_roots: &[AbsolutePathBuf],
_workspace_roots: &[AbsolutePathBuf],
thread_params_mode: ThreadParamsMode,
) -> (
Option<codex_app_server_protocol::SandboxPolicy>,
Option<PermissionProfileSelectionParams>,
) {
let permissions = if matches!(thread_params_mode, ThreadParamsMode::Embedded) {
active_permission_profile
.map(|active| permissions_selection_from_active_profile(active, cwd, workspace_roots))
active_permission_profile.map(permissions_selection_from_active_profile)
} else {
None
};
@@ -1231,13 +1224,7 @@ fn permissions_selection_from_config(
config
.permissions
.active_permission_profile()
.map(|active| {
permissions_selection_from_active_profile(
active,
config.cwd.as_path(),
config.permissions.user_visible_workspace_roots(),
)
})
.map(permissions_selection_from_active_profile)
}
fn thread_start_params_from_config(
@@ -1261,6 +1248,13 @@ fn thread_start_params_from_config(
model_provider: thread_params_mode.model_provider_from_config(config),
service_tier: service_tier_override_from_config(config),
cwd: thread_cwd_from_config(config, thread_params_mode, remote_cwd_override),
runtime_workspace_roots: Some(
config
.workspace_roots
.iter()
.map(AbsolutePathBuf::to_path_buf)
.collect(),
),
approval_policy: Some(config.permissions.approval_policy.value().into()),
approvals_reviewer: approvals_reviewer_override_from_config(config),
sandbox,
@@ -1296,6 +1290,13 @@ fn thread_resume_params_from_config(
model_provider: thread_params_mode.model_provider_from_config(&config),
service_tier: service_tier_override_from_config(&config),
cwd: thread_cwd_from_config(&config, thread_params_mode, remote_cwd_override),
runtime_workspace_roots: Some(
config
.workspace_roots
.iter()
.map(AbsolutePathBuf::to_path_buf)
.collect(),
),
approval_policy: Some(config.permissions.approval_policy.value().into()),
approvals_reviewer: approvals_reviewer_override_from_config(&config),
sandbox,
@@ -1328,6 +1329,13 @@ fn thread_fork_params_from_config(
model_provider: thread_params_mode.model_provider_from_config(&config),
service_tier: service_tier_override_from_config(&config),
cwd: thread_cwd_from_config(&config, thread_params_mode, remote_cwd_override),
runtime_workspace_roots: Some(
config
.workspace_roots
.iter()
.map(AbsolutePathBuf::to_path_buf)
.collect(),
),
approval_policy: Some(config.permissions.approval_policy.value().into()),
approvals_reviewer: approvals_reviewer_override_from_config(&config),
sandbox,
@@ -1425,6 +1433,7 @@ async fn thread_session_state_from_thread_start_response(
permission_profile,
response.active_permission_profile.clone().map(Into::into),
response.cwd.clone(),
response.runtime_workspace_roots.clone(),
response.instruction_sources.clone(),
response.reasoning_effort,
config,
@@ -1457,6 +1466,7 @@ async fn thread_session_state_from_thread_resume_response(
permission_profile,
response.active_permission_profile.clone().map(Into::into),
response.cwd.clone(),
response.runtime_workspace_roots.clone(),
response.instruction_sources.clone(),
response.reasoning_effort,
config,
@@ -1489,6 +1499,7 @@ async fn thread_session_state_from_thread_fork_response(
permission_profile,
response.active_permission_profile.clone().map(Into::into),
response.cwd.clone(),
response.runtime_workspace_roots.clone(),
response.instruction_sources.clone(),
response.reasoning_effort,
config,
@@ -1531,6 +1542,7 @@ async fn thread_session_state_from_thread_response(
permission_profile: PermissionProfile,
active_permission_profile: Option<ActivePermissionProfile>,
cwd: AbsolutePathBuf,
runtime_workspace_roots: Vec<AbsolutePathBuf>,
instruction_source_paths: Vec<AbsolutePathBuf>,
reasoning_effort: Option<codex_protocol::openai_models::ReasoningEffort>,
config: &Config,
@@ -1558,6 +1570,7 @@ async fn thread_session_state_from_thread_response(
permission_profile,
active_permission_profile,
cwd,
runtime_workspace_roots,
instruction_source_paths,
reasoning_effort,
message_history: Some(MessageHistoryMetadata {
@@ -1637,19 +1650,23 @@ mod tests {
);
assert_eq!(params.cwd, Some(config.cwd.to_string_lossy().to_string()));
assert_eq!(
params.runtime_workspace_roots,
Some(
config
.workspace_roots
.iter()
.map(AbsolutePathBuf::to_path_buf)
.collect()
)
);
assert_eq!(params.sandbox, None);
assert_eq!(
params.permissions,
config
.permissions
.active_permission_profile()
.map(|active| {
permissions_selection_from_active_profile(
active,
config.cwd.as_path(),
config.permissions.user_visible_workspace_roots(),
)
})
.map(permissions_selection_from_active_profile)
);
assert_eq!(params.model_provider, Some(config.model_provider_id));
assert_eq!(params.thread_source, Some(ThreadSource::User));
@@ -1676,11 +1693,8 @@ mod tests {
let active_permission_profile =
ActivePermissionProfile::new(BUILT_IN_PERMISSION_PROFILE_WORKSPACE);
let workspace_roots = vec![cwd.clone()];
let expected_permissions = permissions_selection_from_active_profile(
active_permission_profile.clone(),
cwd.as_path(),
&workspace_roots,
);
let expected_permissions =
permissions_selection_from_active_profile(active_permission_profile.clone());
let (sandbox_policy, permissions) = turn_permissions_overrides(
&PermissionProfile::workspace_write(),
@@ -1695,12 +1709,12 @@ mod tests {
}
#[test]
fn embedded_turn_permissions_include_extra_workspace_roots_as_modifications() {
fn embedded_turn_permissions_select_profile_id_only() {
let cwd = test_path_buf("/workspace/project").abs();
let extra_root = test_path_buf("/workspace/cache").abs();
let active_permission_profile =
ActivePermissionProfile::new(BUILT_IN_PERMISSION_PROFILE_WORKSPACE);
let workspace_roots = vec![cwd.clone(), extra_root.clone()];
let workspace_roots = vec![cwd.clone(), extra_root];
let (sandbox_policy, permissions) = turn_permissions_overrides(
&PermissionProfile::workspace_write(),
@@ -1713,14 +1727,9 @@ mod tests {
assert_eq!(sandbox_policy, None);
assert_eq!(
permissions,
Some(PermissionProfileSelectionParams::Profile {
id: BUILT_IN_PERMISSION_PROFILE_WORKSPACE.to_string(),
modifications: Some(vec![
PermissionProfileModificationParams::AdditionalWritableRoot {
path: extra_root
}
]),
})
Some(PermissionProfileSelectionParams::new(
BUILT_IN_PERMISSION_PROFILE_WORKSPACE
))
);
}
@@ -1777,6 +1786,13 @@ mod tests {
&config.permissions.effective_permission_profile(),
config.cwd.as_path(),
);
let expected_runtime_workspace_roots = Some(
config
.workspace_roots
.iter()
.map(AbsolutePathBuf::to_path_buf)
.collect::<Vec<_>>(),
);
let start = thread_start_params_from_config(
&config,
@@ -1800,6 +1816,18 @@ mod tests {
assert_eq!(start.cwd, None);
assert_eq!(resume.cwd, None);
assert_eq!(fork.cwd, None);
assert_eq!(
start.runtime_workspace_roots,
expected_runtime_workspace_roots
);
assert_eq!(
resume.runtime_workspace_roots,
expected_runtime_workspace_roots
);
assert_eq!(
fork.runtime_workspace_roots,
expected_runtime_workspace_roots
);
assert_eq!(start.model_provider, None);
assert_eq!(resume.model_provider, None);
assert_eq!(fork.model_provider, None);
@@ -2070,6 +2098,10 @@ mod tests {
model_provider: "openai".to_string(),
service_tier: None,
cwd: test_path_buf("/tmp/project").abs(),
runtime_workspace_roots: vec![
test_path_buf("/tmp/project").abs(),
test_path_buf("/tmp/project/extra").abs(),
],
instruction_sources: vec![test_path_buf("/tmp/project/AGENTS.md").abs()],
approval_policy: codex_app_server_protocol::AskForApproval::Never,
approvals_reviewer: codex_app_server_protocol::ApprovalsReviewer::User,
@@ -2090,6 +2122,10 @@ mod tests {
.await
.expect("resume response should map");
assert_eq!(started.session.forked_from_id, Some(forked_from_id));
assert_eq!(
started.session.runtime_workspace_roots,
response.runtime_workspace_roots
);
assert_eq!(
started.session.instruction_source_paths,
response.instruction_sources
@@ -2097,6 +2133,17 @@ mod tests {
assert_eq!(started.session.permission_profile, read_only_profile);
assert_eq!(started.turns.len(), 1);
assert_eq!(started.turns[0], response.thread.turns[0]);
let mut empty_roots_response = response;
empty_roots_response.runtime_workspace_roots = Vec::new();
let started = started_thread_from_resume_response(
empty_roots_response,
&config,
ThreadParamsMode::Remote,
)
.await
.expect("resume response should map");
assert_eq!(started.session.runtime_workspace_roots, Vec::new());
}
#[tokio::test]
@@ -2193,6 +2240,7 @@ mod tests {
/*active_permission_profile*/ None,
test_path_buf("/tmp/project").abs(),
Vec::new(),
Vec::new(),
/*reasoning_effort*/ None,
&config,
)
@@ -2227,6 +2275,7 @@ mod tests {
/*active_permission_profile*/ None,
test_path_buf("/tmp/project").abs(),
Vec::new(),
Vec::new(),
/*reasoning_effort*/ None,
&config,
)
+5 -19
View File
@@ -32,26 +32,12 @@ impl ChatWidget {
self.forked_from = session.forked_from_id;
self.current_rollout_path = session.rollout_path.clone();
self.current_cwd = Some(session.cwd.to_path_buf());
let previous_cwd = self.config.cwd.clone();
let previous_workspace_roots = self.config.workspace_roots.clone();
self.config.cwd = session.cwd.clone();
if !self.config.workspace_roots_explicit {
let mut workspace_roots = vec![session.cwd.clone()];
if previous_workspace_roots
.iter()
.any(|root| root == &previous_cwd)
{
for root in previous_workspace_roots {
if root != previous_cwd
&& !workspace_roots.iter().any(|existing| existing == &root)
{
workspace_roots.push(root);
}
}
}
self.config.workspace_roots = workspace_roots.clone();
self.config.permissions.set_workspace_roots(workspace_roots);
}
let runtime_workspace_roots = session.runtime_workspace_roots.clone();
self.config.workspace_roots = runtime_workspace_roots.clone();
self.config
.permissions
.set_workspace_roots(runtime_workspace_roots);
self.effective_service_tier = session.service_tier.clone();
if let Err(err) = self
.config
@@ -28,6 +28,7 @@ async fn submission_preserves_text_elements_and_local_images() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -131,6 +132,7 @@ async fn submission_includes_configured_permission_profile() {
permission_profile: expected_permission_profile.clone(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -180,6 +182,7 @@ async fn submission_keeps_profile_when_legacy_projection_is_external() {
permission_profile: expected_permission_profile.clone(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -221,6 +224,7 @@ async fn submission_with_remote_and_local_images_keeps_local_placeholder_numberi
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -314,6 +318,7 @@ async fn enter_with_only_remote_images_submits_user_turn() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -377,6 +382,7 @@ async fn shift_enter_with_only_remote_images_does_not_submit_user_turn() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -415,6 +421,7 @@ async fn enter_with_only_remote_images_does_not_submit_when_modal_is_active() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -453,6 +460,7 @@ async fn enter_with_only_remote_images_does_not_submit_when_input_disabled() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -494,6 +502,7 @@ async fn submission_prefers_selected_duplicate_skill_path() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -957,6 +957,7 @@ async fn bang_shell_enter_while_task_running_submits_run_user_shell_command() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -29,6 +29,7 @@ async fn resumed_initial_messages_render_history() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -99,6 +100,7 @@ async fn replayed_user_message_preserves_text_elements_and_local_images() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -167,6 +169,7 @@ async fn replayed_user_message_preserves_remote_image_urls() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -266,6 +269,7 @@ async fn session_configured_syncs_widget_config_permissions_and_cwd() {
permission_profile: expected_permission_profile,
active_permission_profile: None,
cwd: expected_cwd.clone(),
runtime_workspace_roots: vec![expected_cwd.clone()],
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -293,13 +297,14 @@ async fn session_configured_syncs_widget_config_permissions_and_cwd() {
chat.set_permission_profile(updated_profile.clone())
.expect("set permission profile");
assert_eq!(
chat.config_ref().permissions.permission_profile().get(),
chat.config_ref().permissions.permission_profile(),
&updated_profile,
"local permission changes should replace SessionConfigured canonical permissions"
);
assert_eq!(
chat.config_ref().permissions.effective_permission_profile(),
updated_profile
.clone()
.materialize_project_roots_with_workspace_roots(std::slice::from_ref(&expected_cwd)),
"effective permissions should still use the current thread runtime workspace roots"
);
@@ -380,6 +385,7 @@ async fn session_configured_external_sandbox_keeps_external_runtime_policy() {
permission_profile: expected_permission_profile,
active_permission_profile: None,
cwd: test_path_buf("/home/user/external").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -420,6 +426,7 @@ async fn replayed_user_message_with_only_remote_images_renders_history_cell() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -474,6 +481,7 @@ async fn replayed_user_message_with_only_local_images_renders_history_cell() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -744,6 +752,7 @@ async fn replayed_reasoning_item_hides_raw_reasoning_when_disabled() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_project_path().abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: None,
message_history: None,
@@ -789,6 +798,7 @@ async fn replayed_reasoning_item_shows_raw_reasoning_when_enabled() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_project_path().abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: None,
message_history: None,
@@ -584,6 +584,7 @@ async fn permissions_selection_marks_auto_review_current_after_session_configure
permission_profile: PermissionProfile::workspace_write(),
active_permission_profile: None,
cwd: test_project_path().abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: None,
message_history: None,
@@ -631,6 +632,7 @@ async fn permissions_selection_marks_auto_review_current_with_custom_workspace_w
permission_profile,
active_permission_profile: None,
cwd,
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: None,
message_history: None,
@@ -1217,6 +1217,7 @@ async fn submit_user_message_emits_structured_plugin_mentions_from_bindings() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -1403,6 +1404,7 @@ async fn plan_slash_command_with_args_submits_prompt_in_plan_mode() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
@@ -2230,6 +2230,7 @@ async fn session_configured_clears_goal_status_footer() {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
message_history: None,
+1
View File
@@ -3959,6 +3959,7 @@ mod tests {
permission_profile: PermissionProfile::read_only(),
active_permission_profile: None,
cwd: test_path_buf("/tmp/project").abs(),
runtime_workspace_roots: Vec::new(),
instruction_source_paths: Vec::new(),
reasoning_effort: None,
message_history: None,
+1
View File
@@ -42,6 +42,7 @@ pub(crate) struct ThreadSessionState {
/// when the server knows it.
pub(crate) active_permission_profile: Option<ActivePermissionProfile>,
pub(crate) cwd: AbsolutePathBuf,
pub(crate) runtime_workspace_roots: Vec<AbsolutePathBuf>,
pub(crate) instruction_source_paths: Vec<AbsolutePathBuf>,
pub(crate) reasoning_effort: Option<codex_protocol::openai_models::ReasoningEffort>,
pub(crate) message_history: Option<MessageHistoryMetadata>,