mirror of
https://github.com/openai/codex.git
synced 2026-04-26 23:55:25 +00:00
Assemble sandbox/approval/network prompts dynamically (#8961)
- Add a single builder for developer permissions messaging that accepts SandboxPolicy and approval policy. This builder now drives the developer “permissions” message that’s injected at session start and any time sandbox/approval settings change. - Trim EnvironmentContext to only include cwd, writable roots, and shell; removed sandbox/approval/network duplication and adjusted XML serialization and tests accordingly. Follow-up: adding a config value to replace the developer permissions message for custom sandboxes.
This commit is contained in:
@@ -284,7 +284,7 @@ async fn resume_includes_initial_messages_and_sends_prior_items() {
|
||||
let expected_initial_json = json!([]);
|
||||
assert_eq!(initial_json, expected_initial_json);
|
||||
|
||||
// 2) Submit new input; the request body must include the prior item followed by the new user input.
|
||||
// 2) Submit new input; the request body must include the prior items, then initial context, then new user input.
|
||||
codex
|
||||
.submit(Op::UserInput {
|
||||
items: vec![UserInput::Text {
|
||||
@@ -298,24 +298,55 @@ async fn resume_includes_initial_messages_and_sends_prior_items() {
|
||||
|
||||
let request = resp_mock.single_request();
|
||||
let request_body = request.body_json();
|
||||
let expected_input = json!([
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [{ "type": "input_text", "text": "resumed user message" }]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "assistant",
|
||||
"content": [{ "type": "output_text", "text": "resumed assistant message" }]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [{ "type": "input_text", "text": "hello" }]
|
||||
}
|
||||
]);
|
||||
assert_eq!(request_body["input"], expected_input);
|
||||
let input = request_body["input"].as_array().expect("input array");
|
||||
let messages: Vec<(String, String)> = input
|
||||
.iter()
|
||||
.filter_map(|item| {
|
||||
let role = item.get("role")?.as_str()?;
|
||||
let text = item
|
||||
.get("content")?
|
||||
.as_array()?
|
||||
.first()?
|
||||
.get("text")?
|
||||
.as_str()?;
|
||||
Some((role.to_string(), text.to_string()))
|
||||
})
|
||||
.collect();
|
||||
let pos_prior_user = messages
|
||||
.iter()
|
||||
.position(|(role, text)| role == "user" && text == "resumed user message")
|
||||
.expect("prior user message");
|
||||
let pos_prior_assistant = messages
|
||||
.iter()
|
||||
.position(|(role, text)| role == "assistant" && text == "resumed assistant message")
|
||||
.expect("prior assistant message");
|
||||
let pos_permissions = messages
|
||||
.iter()
|
||||
.position(|(role, text)| role == "developer" && text.contains("`approval_policy`"))
|
||||
.expect("permissions message");
|
||||
let pos_user_instructions = messages
|
||||
.iter()
|
||||
.position(|(role, text)| {
|
||||
role == "user"
|
||||
&& text.contains("be nice")
|
||||
&& (text.starts_with("# AGENTS.md instructions for ")
|
||||
|| text.starts_with("<user_instructions>"))
|
||||
})
|
||||
.expect("user instructions");
|
||||
let pos_environment = messages
|
||||
.iter()
|
||||
.position(|(role, text)| role == "user" && text.contains("<environment_context>"))
|
||||
.expect("environment context");
|
||||
let pos_new_user = messages
|
||||
.iter()
|
||||
.position(|(role, text)| role == "user" && text == "hello")
|
||||
.expect("new user message");
|
||||
|
||||
assert!(pos_prior_user < pos_prior_assistant);
|
||||
assert!(pos_prior_assistant < pos_permissions);
|
||||
assert!(pos_permissions < pos_user_instructions);
|
||||
assert!(pos_user_instructions < pos_environment);
|
||||
assert!(pos_environment < pos_new_user);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
@@ -615,17 +646,26 @@ async fn includes_user_instructions_message_in_request() {
|
||||
.unwrap()
|
||||
.contains("be nice")
|
||||
);
|
||||
assert_message_role(&request_body["input"][0], "user");
|
||||
assert_message_starts_with(&request_body["input"][0], "# AGENTS.md instructions for ");
|
||||
assert_message_ends_with(&request_body["input"][0], "</INSTRUCTIONS>");
|
||||
let ui_text = request_body["input"][0]["content"][0]["text"]
|
||||
assert_message_role(&request_body["input"][0], "developer");
|
||||
let permissions_text = request_body["input"][0]["content"][0]["text"]
|
||||
.as_str()
|
||||
.expect("invalid permissions message content");
|
||||
assert!(
|
||||
permissions_text.contains("`sandbox_mode`"),
|
||||
"expected permissions message to mention sandbox_mode, got {permissions_text:?}"
|
||||
);
|
||||
|
||||
assert_message_role(&request_body["input"][1], "user");
|
||||
assert_message_starts_with(&request_body["input"][1], "# AGENTS.md instructions for ");
|
||||
assert_message_ends_with(&request_body["input"][1], "</INSTRUCTIONS>");
|
||||
let ui_text = request_body["input"][1]["content"][0]["text"]
|
||||
.as_str()
|
||||
.expect("invalid message content");
|
||||
assert!(ui_text.contains("<INSTRUCTIONS>"));
|
||||
assert!(ui_text.contains("be nice"));
|
||||
assert_message_role(&request_body["input"][1], "user");
|
||||
assert_message_starts_with(&request_body["input"][1], "<environment_context>");
|
||||
assert_message_ends_with(&request_body["input"][1], "</environment_context>");
|
||||
assert_message_role(&request_body["input"][2], "user");
|
||||
assert_message_starts_with(&request_body["input"][2], "<environment_context>");
|
||||
assert_message_ends_with(&request_body["input"][2], "</environment_context>");
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
@@ -679,8 +719,10 @@ async fn skills_append_to_instructions() {
|
||||
let request = resp_mock.single_request();
|
||||
let request_body = request.body_json();
|
||||
|
||||
assert_message_role(&request_body["input"][0], "user");
|
||||
let instructions_text = request_body["input"][0]["content"][0]["text"]
|
||||
assert_message_role(&request_body["input"][0], "developer");
|
||||
|
||||
assert_message_role(&request_body["input"][1], "user");
|
||||
let instructions_text = request_body["input"][1]["content"][0]["text"]
|
||||
.as_str()
|
||||
.expect("instructions text");
|
||||
assert!(
|
||||
@@ -1046,6 +1088,10 @@ async fn includes_developer_instructions_message_in_request() {
|
||||
let request = resp_mock.single_request();
|
||||
let request_body = request.body_json();
|
||||
|
||||
let permissions_text = request_body["input"][0]["content"][0]["text"]
|
||||
.as_str()
|
||||
.expect("invalid permissions message content");
|
||||
|
||||
assert!(
|
||||
!request_body["instructions"]
|
||||
.as_str()
|
||||
@@ -1053,18 +1099,24 @@ async fn includes_developer_instructions_message_in_request() {
|
||||
.contains("be nice")
|
||||
);
|
||||
assert_message_role(&request_body["input"][0], "developer");
|
||||
assert_message_equals(&request_body["input"][0], "be useful");
|
||||
assert_message_role(&request_body["input"][1], "user");
|
||||
assert_message_starts_with(&request_body["input"][1], "# AGENTS.md instructions for ");
|
||||
assert_message_ends_with(&request_body["input"][1], "</INSTRUCTIONS>");
|
||||
let ui_text = request_body["input"][1]["content"][0]["text"]
|
||||
assert!(
|
||||
permissions_text.contains("`sandbox_mode`"),
|
||||
"expected permissions message to mention sandbox_mode, got {permissions_text:?}"
|
||||
);
|
||||
|
||||
assert_message_role(&request_body["input"][1], "developer");
|
||||
assert_message_equals(&request_body["input"][1], "be useful");
|
||||
assert_message_role(&request_body["input"][2], "user");
|
||||
assert_message_starts_with(&request_body["input"][2], "# AGENTS.md instructions for ");
|
||||
assert_message_ends_with(&request_body["input"][2], "</INSTRUCTIONS>");
|
||||
let ui_text = request_body["input"][2]["content"][0]["text"]
|
||||
.as_str()
|
||||
.expect("invalid message content");
|
||||
assert!(ui_text.contains("<INSTRUCTIONS>"));
|
||||
assert!(ui_text.contains("be nice"));
|
||||
assert_message_role(&request_body["input"][2], "user");
|
||||
assert_message_starts_with(&request_body["input"][2], "<environment_context>");
|
||||
assert_message_ends_with(&request_body["input"][2], "</environment_context>");
|
||||
assert_message_role(&request_body["input"][3], "user");
|
||||
assert_message_starts_with(&request_body["input"][3], "<environment_context>");
|
||||
assert_message_ends_with(&request_body["input"][3], "</environment_context>");
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
|
||||
Reference in New Issue
Block a user