mirror of
https://github.com/openai/codex.git
synced 2026-10-28 08:04:55 +00:00
Refactor world-state rendering tests into snapshots (#33412)
## What changed - Add a shared test helper that renders before-and-after section states alongside the resulting role and content. - Convert the agents, environment, apps, and plugins world-state tests to snapshot tables covering absent, unknown, unchanged, changed, and removed states. GitOrigin-RevId: 03372a5f925d2019f37bf5a5a2f060261899026c
This commit is contained in:
@@ -1,101 +1,29 @@
|
||||
use super::super::PreviousSectionState;
|
||||
use super::super::test_support::render_section_cases;
|
||||
use super::*;
|
||||
use crate::context::world_state::WorldState;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn renders_full_state_and_omits_unchanged_state() {
|
||||
let loaded = LoadedAgentsMd::from_text_for_testing("use the project formatter");
|
||||
let mut state = WorldState::default();
|
||||
state.add_section(AgentsMdState::new(Some(&loaded)));
|
||||
fn snapshots() {
|
||||
use PreviousSectionState::Absent;
|
||||
use PreviousSectionState::Known;
|
||||
use PreviousSectionState::Unknown;
|
||||
|
||||
assert_eq!(
|
||||
vec![user_message(
|
||||
"# AGENTS.md instructions\n\n<INSTRUCTIONS>\nuse the project formatter\n</INSTRUCTIONS>",
|
||||
)],
|
||||
render_fragments(state.render_full()),
|
||||
);
|
||||
assert_eq!(
|
||||
Vec::<ResponseItem>::new(),
|
||||
render_fragments(state.render_diff(&state.snapshot()))
|
||||
);
|
||||
assert_eq!(
|
||||
state.snapshot().into_value(),
|
||||
json!({"agents_md": {"text": "use the project formatter"}}),
|
||||
);
|
||||
}
|
||||
let empty = AgentsMdState::default();
|
||||
let project_formatter = LoadedAgentsMd::from_text_for_testing("use the project formatter");
|
||||
let project_formatter = AgentsMdState::new(Some(&project_formatter));
|
||||
let old = LoadedAgentsMd::from_text_for_testing("old instructions");
|
||||
let old = AgentsMdState::new(Some(&old));
|
||||
let new = LoadedAgentsMd::from_text_for_testing("new instructions");
|
||||
let new = AgentsMdState::new(Some(&new));
|
||||
|
||||
#[test]
|
||||
fn changed_and_removed_state_supersedes_previous_instructions() {
|
||||
let previous_loaded = LoadedAgentsMd::from_text_for_testing("old instructions");
|
||||
let mut previous = WorldState::default();
|
||||
previous.add_section(AgentsMdState::new(Some(&previous_loaded)));
|
||||
|
||||
let current_loaded = LoadedAgentsMd::from_text_for_testing("new instructions");
|
||||
let mut current = WorldState::default();
|
||||
current.add_section(AgentsMdState::new(Some(¤t_loaded)));
|
||||
assert_eq!(
|
||||
vec![user_message(
|
||||
"# AGENTS.md instructions\n\n<INSTRUCTIONS>\nThese AGENTS.md instructions replace all previously provided AGENTS.md instructions.\n\nnew instructions\n</INSTRUCTIONS>",
|
||||
)],
|
||||
render_fragments(current.render_diff(&previous.snapshot())),
|
||||
);
|
||||
|
||||
let mut removed = WorldState::default();
|
||||
removed.add_section(AgentsMdState::default());
|
||||
assert_eq!(
|
||||
vec![user_message(
|
||||
"# AGENTS.md instructions\n\n<INSTRUCTIONS>\nThe previously provided AGENTS.md instructions no longer apply.\n</INSTRUCTIONS>",
|
||||
)],
|
||||
render_fragments(removed.render_diff(¤t.snapshot())),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_previous_state_is_explicitly_superseded() {
|
||||
let loaded = LoadedAgentsMd::from_text_for_testing("current instructions");
|
||||
let current = AgentsMdState::new(Some(&loaded));
|
||||
assert_eq!(
|
||||
vec![user_message(
|
||||
"# AGENTS.md instructions\n\n<INSTRUCTIONS>\nThese AGENTS.md instructions replace all previously provided AGENTS.md instructions.\n\ncurrent instructions\n</INSTRUCTIONS>",
|
||||
)],
|
||||
render_fragments(vec![
|
||||
WorldStateSection::render_diff(¤t, PreviousSectionState::Unknown)
|
||||
.expect("unknown state should be replaced"),
|
||||
]),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
vec![user_message(
|
||||
"# AGENTS.md instructions\n\n<INSTRUCTIONS>\nThe previously provided AGENTS.md instructions no longer apply.\n</INSTRUCTIONS>",
|
||||
)],
|
||||
render_fragments(vec![
|
||||
WorldStateSection::render_diff(
|
||||
&AgentsMdState::default(),
|
||||
PreviousSectionState::Unknown,
|
||||
)
|
||||
.expect("unknown state should be removed"),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
fn render_fragments(fragments: Vec<Box<dyn ContextualUserFragment>>) -> Vec<ResponseItem> {
|
||||
fragments
|
||||
.into_iter()
|
||||
.map(ContextualUserFragment::into_boxed_response_item)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn user_message(text: &str) -> ResponseItem {
|
||||
ResponseItem::Message {
|
||||
id: None,
|
||||
role: "user".to_string(),
|
||||
content: vec![ContentItem::InputText {
|
||||
text: text.to_string(),
|
||||
}],
|
||||
phase: None,
|
||||
internal_chat_message_metadata_passthrough: None,
|
||||
}
|
||||
insta::assert_snapshot!(render_section_cases(&[
|
||||
(Absent, Absent),
|
||||
(Absent, Known(&empty)),
|
||||
(Absent, Known(&project_formatter)),
|
||||
(Known(&project_formatter), Known(&project_formatter)),
|
||||
(Known(&old), Known(&new)),
|
||||
(Known(&new), Known(&empty)),
|
||||
(Unknown, Known(&new)),
|
||||
(Unknown, Known(&empty)),
|
||||
]));
|
||||
}
|
||||
|
||||
@@ -1,40 +1,29 @@
|
||||
use super::*;
|
||||
use crate::context::ContextualUserFragment;
|
||||
use crate::context::world_state::PreviousSectionState;
|
||||
use crate::context::world_state::test_support::render_section_cases;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
fn render(state: AppsInstructionsState, previous: PreviousSectionState<'_, bool>) -> Vec<String> {
|
||||
state
|
||||
.render_diff(previous)
|
||||
.into_iter()
|
||||
.map(|fragment| fragment.render())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn renders_only_when_apps_become_available() {
|
||||
fn snapshots() {
|
||||
use PreviousSectionState::Absent;
|
||||
use PreviousSectionState::Known;
|
||||
use PreviousSectionState::Unknown;
|
||||
|
||||
let unavailable = AppsInstructionsState::new(/*available*/ false);
|
||||
let available = AppsInstructionsState::new(/*available*/ true);
|
||||
let false_snapshot = false;
|
||||
let true_snapshot = true;
|
||||
|
||||
assert_eq!(
|
||||
render(unavailable, PreviousSectionState::Absent),
|
||||
Vec::<String>::new()
|
||||
);
|
||||
assert_eq!(render(available, PreviousSectionState::Absent).len(), 1);
|
||||
assert_eq!(
|
||||
render(available, PreviousSectionState::Known(&false_snapshot)).len(),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
render(available, PreviousSectionState::Known(&true_snapshot)),
|
||||
Vec::<String>::new()
|
||||
);
|
||||
assert_eq!(
|
||||
render(unavailable, PreviousSectionState::Known(&true_snapshot)),
|
||||
Vec::<String>::new()
|
||||
);
|
||||
insta::assert_snapshot!(render_section_cases(&[
|
||||
(Absent, Absent),
|
||||
(Absent, Known(&unavailable)),
|
||||
(Absent, Known(&available)),
|
||||
(Known(&unavailable), Known(&available)),
|
||||
(Known(&available), Known(&available)),
|
||||
(Known(&available), Known(&unavailable)),
|
||||
(Unknown, Known(&unavailable)),
|
||||
(Unknown, Known(&available)),
|
||||
]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
use super::super::PreviousSectionState;
|
||||
use super::super::test_support::render_section_cases;
|
||||
use super::*;
|
||||
use crate::context::ContextualUserFragment;
|
||||
use crate::context::world_state::WorldState;
|
||||
use anyhow::Result;
|
||||
use codex_exec_server::LOCAL_ENVIRONMENT_ID;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn renders_full_environment_state() -> Result<()> {
|
||||
let context = EnvironmentsState {
|
||||
fn snapshots() -> Result<()> {
|
||||
use PreviousSectionState::Absent;
|
||||
use PreviousSectionState::Known;
|
||||
use PreviousSectionState::Unknown;
|
||||
|
||||
let full = EnvironmentsState {
|
||||
environments: [
|
||||
("laptop".to_string(), available("file:///repo", "zsh")?),
|
||||
(
|
||||
@@ -24,34 +24,7 @@ fn renders_full_environment_state() -> Result<()> {
|
||||
.collect(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut world_state = WorldState::default();
|
||||
world_state.add_section(context);
|
||||
|
||||
assert_eq!(
|
||||
vec![user_message(
|
||||
r#"<environment_context>
|
||||
<environments>
|
||||
<environment id="devbox">
|
||||
<cwd>/workspace</cwd>
|
||||
<shell>bash</shell>
|
||||
</environment>
|
||||
<environment id="laptop">
|
||||
<cwd>/repo</cwd>
|
||||
<shell>zsh</shell>
|
||||
</environment>
|
||||
</environments>
|
||||
</environment_context>"#,
|
||||
)],
|
||||
render_fragments(world_state.render_full()),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn renders_only_changed_environments() -> Result<()> {
|
||||
let mut previous = WorldState::default();
|
||||
previous.add_section(EnvironmentsState {
|
||||
let before_environment_changes = EnvironmentsState {
|
||||
environments: [
|
||||
("laptop".to_string(), available("file:///repo", "bash")?),
|
||||
("devbox".to_string(), starting("file:///workspace")?),
|
||||
@@ -60,9 +33,8 @@ fn renders_only_changed_environments() -> Result<()> {
|
||||
.into_iter()
|
||||
.collect(),
|
||||
..Default::default()
|
||||
});
|
||||
let mut current = WorldState::default();
|
||||
current.add_section(EnvironmentsState {
|
||||
};
|
||||
let after_environment_changes = EnvironmentsState {
|
||||
environments: [
|
||||
("laptop".to_string(), available("file:///repo", "zsh")?),
|
||||
(
|
||||
@@ -74,35 +46,7 @@ fn renders_only_changed_environments() -> Result<()> {
|
||||
.into_iter()
|
||||
.collect(),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
vec![user_message(
|
||||
r#"<environment_context>
|
||||
<environments>
|
||||
<environment id="devbox">
|
||||
<cwd>/workspace</cwd>
|
||||
<shell>powershell</shell>
|
||||
</environment>
|
||||
<environment id="laptop">
|
||||
<cwd>/repo</cwd>
|
||||
<shell>zsh</shell>
|
||||
</environment>
|
||||
<environment id="old" status="unavailable" />
|
||||
<environment id="remote">
|
||||
<cwd>/remote</cwd>
|
||||
<status>starting</status>
|
||||
</environment>
|
||||
</environments>
|
||||
</environment_context>"#,
|
||||
)],
|
||||
render_fragments(current.render_diff(&previous.snapshot())),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn persisted_turn_context_values_render_a_diff() -> Result<()> {
|
||||
};
|
||||
let environments = EnvironmentsState {
|
||||
environments: [(
|
||||
LOCAL_ENVIRONMENT_ID.to_string(),
|
||||
@@ -112,8 +56,7 @@ fn persisted_turn_context_values_render_a_diff() -> Result<()> {
|
||||
.collect(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut previous = WorldState::default();
|
||||
previous.add_section(EnvironmentsState {
|
||||
let before_turn_context_changes = EnvironmentsState {
|
||||
current_date: Some("2026-06-19".to_string()),
|
||||
timezone: Some("UTC".to_string()),
|
||||
network: Some(NetworkContext::new(
|
||||
@@ -126,9 +69,8 @@ fn persisted_turn_context_values_render_a_diff() -> Result<()> {
|
||||
&[],
|
||||
)),
|
||||
..environments.clone()
|
||||
});
|
||||
let mut current = WorldState::default();
|
||||
current.add_section(EnvironmentsState {
|
||||
};
|
||||
let after_turn_context_changes = EnvironmentsState {
|
||||
current_date: Some("2026-06-20".to_string()),
|
||||
timezone: Some("America/Los_Angeles".to_string()),
|
||||
network: Some(NetworkContext::new(
|
||||
@@ -143,26 +85,8 @@ fn persisted_turn_context_values_render_a_diff() -> Result<()> {
|
||||
&[],
|
||||
)),
|
||||
..environments
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
vec![user_message(
|
||||
r#"<environment_context>
|
||||
<current_date>2026-06-20</current_date>
|
||||
<timezone>America/Los_Angeles</timezone>
|
||||
<network enabled="true"><allowed>new.example.com</allowed><denied>blocked.example.com</denied></network>
|
||||
<filesystem><permission_profile type="external"><file_system type="external" /></permission_profile></filesystem>
|
||||
</environment_context>"#,
|
||||
)],
|
||||
render_fragments(current.render_diff(&previous.snapshot())),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn persisted_snapshot_uses_model_visible_path_and_context_values() -> Result<()> {
|
||||
let mut world_state = WorldState::default();
|
||||
world_state.add_section(EnvironmentsState {
|
||||
};
|
||||
let foreign_windows = EnvironmentsState {
|
||||
environments: [(
|
||||
"remote".to_string(),
|
||||
available("file:///C:/windows", "powershell")?,
|
||||
@@ -174,29 +98,8 @@ fn persisted_snapshot_uses_model_visible_path_and_context_values() -> Result<()>
|
||||
&[],
|
||||
)),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
serde_json::to_value(world_state.snapshot())?,
|
||||
json!({
|
||||
"environments": {
|
||||
"environments": {
|
||||
"remote": {
|
||||
"cwd": "C:\\windows",
|
||||
"status": "available",
|
||||
"shell": "powershell"
|
||||
}
|
||||
},
|
||||
"filesystem": "<filesystem><permission_profile type=\"disabled\"><file_system type=\"unrestricted\" /></permission_profile></filesystem>"
|
||||
}
|
||||
}),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_environment_diff_ignores_unknown_shell() -> Result<()> {
|
||||
let previous = EnvironmentsState {
|
||||
};
|
||||
let unknown_shell = EnvironmentsState {
|
||||
environments: [(
|
||||
LOCAL_ENVIRONMENT_ID.to_string(),
|
||||
EnvironmentState {
|
||||
@@ -209,7 +112,7 @@ fn single_environment_diff_ignores_unknown_shell() -> Result<()> {
|
||||
.collect(),
|
||||
..Default::default()
|
||||
};
|
||||
let current = EnvironmentsState {
|
||||
let known_shell = EnvironmentsState {
|
||||
environments: [(
|
||||
LOCAL_ENVIRONMENT_ID.to_string(),
|
||||
available("file:///repo", "zsh")?,
|
||||
@@ -218,21 +121,7 @@ fn single_environment_diff_ignores_unknown_shell() -> Result<()> {
|
||||
.collect(),
|
||||
..Default::default()
|
||||
};
|
||||
let previous = WorldStateSection::snapshot(&previous);
|
||||
|
||||
assert_eq!(
|
||||
None,
|
||||
render_fragment(WorldStateSection::render_diff(
|
||||
¤t,
|
||||
PreviousSectionState::Known(&previous),
|
||||
))
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn removed_legacy_environment_renders_unavailable() -> Result<()> {
|
||||
let previous = EnvironmentsState {
|
||||
let legacy_environment = EnvironmentsState {
|
||||
environments: [(
|
||||
LOCAL_ENVIRONMENT_ID.to_string(),
|
||||
available("file:///repo", "bash")?,
|
||||
@@ -241,21 +130,24 @@ fn removed_legacy_environment_renders_unavailable() -> Result<()> {
|
||||
.collect(),
|
||||
..Default::default()
|
||||
};
|
||||
let previous = WorldStateSection::snapshot(&previous);
|
||||
let empty = EnvironmentsState::default();
|
||||
|
||||
assert_eq!(
|
||||
Some(user_message(
|
||||
r#"<environment_context>
|
||||
<environments>
|
||||
<environment id="local" status="unavailable" />
|
||||
</environments>
|
||||
</environment_context>"#,
|
||||
)),
|
||||
render_fragment(WorldStateSection::render_diff(
|
||||
&EnvironmentsState::default(),
|
||||
PreviousSectionState::Known(&previous),
|
||||
)),
|
||||
);
|
||||
insta::assert_snapshot!(render_section_cases(&[
|
||||
(Absent, Absent),
|
||||
(Absent, Known(&full)),
|
||||
(Unknown, Known(&full)),
|
||||
(
|
||||
Known(&before_environment_changes),
|
||||
Known(&after_environment_changes),
|
||||
),
|
||||
(
|
||||
Known(&before_turn_context_changes),
|
||||
Known(&after_turn_context_changes),
|
||||
),
|
||||
(Absent, Known(&foreign_windows)),
|
||||
(Known(&unknown_shell), Known(&known_shell)),
|
||||
(Known(&legacy_environment), Known(&empty)),
|
||||
]));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -274,26 +166,3 @@ fn starting(cwd: &str) -> Result<EnvironmentState> {
|
||||
shell: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn render_fragments(fragments: Vec<Box<dyn ContextualUserFragment>>) -> Vec<ResponseItem> {
|
||||
fragments
|
||||
.into_iter()
|
||||
.map(ContextualUserFragment::into_boxed_response_item)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn render_fragment(fragment: Option<Box<dyn ContextualUserFragment>>) -> Option<ResponseItem> {
|
||||
fragment.map(ContextualUserFragment::into_boxed_response_item)
|
||||
}
|
||||
|
||||
fn user_message(text: &str) -> ResponseItem {
|
||||
ResponseItem::Message {
|
||||
id: None,
|
||||
role: "user".to_string(),
|
||||
content: vec![ContentItem::InputText {
|
||||
text: text.to_string(),
|
||||
}],
|
||||
phase: None,
|
||||
internal_chat_message_metadata_passthrough: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ mod agents_md;
|
||||
mod apps_instructions;
|
||||
mod environment;
|
||||
mod plugins_instructions;
|
||||
#[cfg(test)]
|
||||
mod test_support;
|
||||
|
||||
use crate::context::ContextualUserFragment;
|
||||
use codex_extension_api::PreviousWorldStateSection;
|
||||
|
||||
@@ -1,43 +1,29 @@
|
||||
use super::*;
|
||||
use crate::context::ContextualUserFragment;
|
||||
use crate::context::world_state::PreviousSectionState;
|
||||
use crate::context::world_state::test_support::render_section_cases;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
fn render(
|
||||
state: PluginsInstructionsState,
|
||||
previous: PreviousSectionState<'_, bool>,
|
||||
) -> Vec<String> {
|
||||
state
|
||||
.render_diff(previous)
|
||||
.into_iter()
|
||||
.map(|fragment| fragment.render())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn renders_only_when_plugins_become_available() {
|
||||
fn snapshots() {
|
||||
use PreviousSectionState::Absent;
|
||||
use PreviousSectionState::Known;
|
||||
use PreviousSectionState::Unknown;
|
||||
|
||||
let unavailable = PluginsInstructionsState::new(/*available*/ false);
|
||||
let available = PluginsInstructionsState::new(/*available*/ true);
|
||||
let false_snapshot = false;
|
||||
let true_snapshot = true;
|
||||
|
||||
assert_eq!(
|
||||
render(unavailable, PreviousSectionState::Absent),
|
||||
Vec::<String>::new()
|
||||
);
|
||||
assert_eq!(render(available, PreviousSectionState::Absent).len(), 1);
|
||||
assert_eq!(
|
||||
render(available, PreviousSectionState::Known(&false_snapshot)).len(),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
render(available, PreviousSectionState::Known(&true_snapshot)),
|
||||
Vec::<String>::new()
|
||||
);
|
||||
assert_eq!(
|
||||
render(unavailable, PreviousSectionState::Known(&true_snapshot)),
|
||||
Vec::<String>::new()
|
||||
);
|
||||
insta::assert_snapshot!(render_section_cases(&[
|
||||
(Absent, Absent),
|
||||
(Absent, Known(&unavailable)),
|
||||
(Absent, Known(&available)),
|
||||
(Known(&unavailable), Known(&available)),
|
||||
(Known(&available), Known(&available)),
|
||||
(Known(&available), Known(&unavailable)),
|
||||
(Unknown, Known(&unavailable)),
|
||||
(Unknown, Known(&available)),
|
||||
]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
---
|
||||
source: core/src/context/world_state/agents_md_tests.rs
|
||||
expression: "render_section_cases(&[(Absent, Absent), (Absent, Known(&empty)),\n(Absent, Known(&project_formatter)),\n(Known(&project_formatter), Known(&project_formatter)),\n(Known(&old), Known(&new)), (Known(&new), Known(&empty)),\n(Unknown, Known(&new)), (Unknown, Known(&empty)),])"
|
||||
---
|
||||
Absent -> Absent
|
||||
None
|
||||
|
||||
Absent -> {}
|
||||
None
|
||||
|
||||
Absent -> {"text":"use the project formatter"} (role - user)
|
||||
# AGENTS.md instructions
|
||||
|
||||
<INSTRUCTIONS>
|
||||
use the project formatter
|
||||
</INSTRUCTIONS>
|
||||
|
||||
{"text":"use the project formatter"} -> {"text":"use the project formatter"}
|
||||
None
|
||||
|
||||
{"text":"old instructions"} -> {"text":"new instructions"} (role - user)
|
||||
# AGENTS.md instructions
|
||||
|
||||
<INSTRUCTIONS>
|
||||
These AGENTS.md instructions replace all previously provided AGENTS.md instructions.
|
||||
|
||||
new instructions
|
||||
</INSTRUCTIONS>
|
||||
|
||||
{"text":"new instructions"} -> {} (role - user)
|
||||
# AGENTS.md instructions
|
||||
|
||||
<INSTRUCTIONS>
|
||||
The previously provided AGENTS.md instructions no longer apply.
|
||||
</INSTRUCTIONS>
|
||||
|
||||
Unknown -> {"text":"new instructions"} (role - user)
|
||||
# AGENTS.md instructions
|
||||
|
||||
<INSTRUCTIONS>
|
||||
These AGENTS.md instructions replace all previously provided AGENTS.md instructions.
|
||||
|
||||
new instructions
|
||||
</INSTRUCTIONS>
|
||||
|
||||
Unknown -> {} (role - user)
|
||||
# AGENTS.md instructions
|
||||
|
||||
<INSTRUCTIONS>
|
||||
The previously provided AGENTS.md instructions no longer apply.
|
||||
</INSTRUCTIONS>
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
---
|
||||
source: core/src/context/world_state/apps_instructions_tests.rs
|
||||
expression: "render_section_cases(&[(Absent, Absent), (Absent, Known(&unavailable)),\n(Absent, Known(&available)), (Known(&unavailable), Known(&available)),\n(Known(&available), Known(&available)),\n(Known(&available), Known(&unavailable)), (Unknown, Known(&unavailable)),\n(Unknown, Known(&available)),])"
|
||||
---
|
||||
Absent -> Absent
|
||||
None
|
||||
|
||||
Absent -> false
|
||||
None
|
||||
|
||||
Absent -> true (role - developer)
|
||||
<apps_instructions>
|
||||
## Apps (Connectors)
|
||||
Apps (Connectors) can be explicitly triggered in user messages in the format `[$app-name](app://{connector_id})`. Apps can also be implicitly triggered as long as the context suggests usage of available apps.
|
||||
An app is equivalent to a set of MCP tools within the `codex_apps` MCP.
|
||||
An installed app's MCP tools are either provided to you already, or can be lazy-loaded through the `tool_search` tool. If `tool_search` is available, the apps that are searchable by `tools_search` will be listed by it.
|
||||
Do not additionally call list_mcp_resources or list_mcp_resource_templates for apps.
|
||||
</apps_instructions>
|
||||
|
||||
false -> true (role - developer)
|
||||
<apps_instructions>
|
||||
## Apps (Connectors)
|
||||
Apps (Connectors) can be explicitly triggered in user messages in the format `[$app-name](app://{connector_id})`. Apps can also be implicitly triggered as long as the context suggests usage of available apps.
|
||||
An app is equivalent to a set of MCP tools within the `codex_apps` MCP.
|
||||
An installed app's MCP tools are either provided to you already, or can be lazy-loaded through the `tool_search` tool. If `tool_search` is available, the apps that are searchable by `tools_search` will be listed by it.
|
||||
Do not additionally call list_mcp_resources or list_mcp_resource_templates for apps.
|
||||
</apps_instructions>
|
||||
|
||||
true -> true
|
||||
None
|
||||
|
||||
true -> false
|
||||
None
|
||||
|
||||
Unknown -> false
|
||||
None
|
||||
|
||||
Unknown -> true
|
||||
None
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
---
|
||||
source: core/src/context/world_state/environment_tests.rs
|
||||
expression: "render_section_cases(&[(Absent, Absent), (Absent, Known(&full)),\n(Unknown, Known(&full)),\n(Known(&before_environment_changes), Known(&after_environment_changes),),\n(Known(&before_turn_context_changes), Known(&after_turn_context_changes),),\n(Absent, Known(&foreign_windows)),\n(Known(&unknown_shell), Known(&known_shell)),\n(Known(&legacy_environment), Known(&empty)),])"
|
||||
---
|
||||
Absent -> Absent
|
||||
None
|
||||
|
||||
Absent -> {"environments":{"devbox":{"cwd":"/workspace","shell":"bash","status":"available"},"laptop":{"cwd":"/repo","shell":"zsh","status":"available"}}} (role - user)
|
||||
<environment_context>
|
||||
<environments>
|
||||
<environment id="devbox">
|
||||
<cwd>/workspace</cwd>
|
||||
<shell>bash</shell>
|
||||
</environment>
|
||||
<environment id="laptop">
|
||||
<cwd>/repo</cwd>
|
||||
<shell>zsh</shell>
|
||||
</environment>
|
||||
</environments>
|
||||
</environment_context>
|
||||
|
||||
Unknown -> {"environments":{"devbox":{"cwd":"/workspace","shell":"bash","status":"available"},"laptop":{"cwd":"/repo","shell":"zsh","status":"available"}}} (role - user)
|
||||
<environment_context>
|
||||
<environments>
|
||||
<environment id="devbox">
|
||||
<cwd>/workspace</cwd>
|
||||
<shell>bash</shell>
|
||||
</environment>
|
||||
<environment id="laptop">
|
||||
<cwd>/repo</cwd>
|
||||
<shell>zsh</shell>
|
||||
</environment>
|
||||
</environments>
|
||||
</environment_context>
|
||||
|
||||
{"environments":{"devbox":{"cwd":"/workspace","status":"starting"},"laptop":{"cwd":"/repo","shell":"bash","status":"available"},"old":{"cwd":"/old","shell":"sh","status":"available"}}} -> {"environments":{"devbox":{"cwd":"/workspace","shell":"powershell","status":"available"},"laptop":{"cwd":"/repo","shell":"zsh","status":"available"},"remote":{"cwd":"/remote","status":"starting"}}} (role - user)
|
||||
<environment_context>
|
||||
<environments>
|
||||
<environment id="devbox">
|
||||
<cwd>/workspace</cwd>
|
||||
<shell>powershell</shell>
|
||||
</environment>
|
||||
<environment id="laptop">
|
||||
<cwd>/repo</cwd>
|
||||
<shell>zsh</shell>
|
||||
</environment>
|
||||
<environment id="old" status="unavailable" />
|
||||
<environment id="remote">
|
||||
<cwd>/remote</cwd>
|
||||
<status>starting</status>
|
||||
</environment>
|
||||
</environments>
|
||||
</environment_context>
|
||||
|
||||
{"current_date":"2026-06-19","environments":{"local":{"cwd":"/repo","shell":"zsh","status":"available"}},"filesystem":"<filesystem><permission_profile type=\"disabled\"><file_system type=\"unrestricted\" /></permission_profile></filesystem>","network":"<network enabled=\"true\"><allowed>old.example.com</allowed></network>","timezone":"UTC"} -> {"current_date":"2026-06-20","environments":{"local":{"cwd":"/repo","shell":"zsh","status":"available"}},"filesystem":"<filesystem><permission_profile type=\"external\"><file_system type=\"external\" /></permission_profile></filesystem>","network":"<network enabled=\"true\"><allowed>new.example.com</allowed><denied>blocked.example.com</denied></network>","timezone":"America/Los_Angeles"} (role - user)
|
||||
<environment_context>
|
||||
<current_date>2026-06-20</current_date>
|
||||
<timezone>America/Los_Angeles</timezone>
|
||||
<network enabled="true"><allowed>new.example.com</allowed><denied>blocked.example.com</denied></network>
|
||||
<filesystem><permission_profile type="external"><file_system type="external" /></permission_profile></filesystem>
|
||||
</environment_context>
|
||||
|
||||
Absent -> {"environments":{"remote":{"cwd":"C:\\windows","shell":"powershell","status":"available"}},"filesystem":"<filesystem><permission_profile type=\"disabled\"><file_system type=\"unrestricted\" /></permission_profile></filesystem>"} (role - user)
|
||||
<environment_context>
|
||||
<cwd>C:\windows</cwd>
|
||||
<shell>powershell</shell>
|
||||
<filesystem><permission_profile type="disabled"><file_system type="unrestricted" /></permission_profile></filesystem>
|
||||
</environment_context>
|
||||
|
||||
{"environments":{"local":{"cwd":"/repo","status":"available"}}} -> {"environments":{"local":{"cwd":"/repo","shell":"zsh","status":"available"}}}
|
||||
None
|
||||
|
||||
{"environments":{"local":{"cwd":"/repo","shell":"bash","status":"available"}}} -> {"environments":{}} (role - user)
|
||||
<environment_context>
|
||||
<environments>
|
||||
<environment id="local" status="unavailable" />
|
||||
</environments>
|
||||
</environment_context>
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
---
|
||||
source: core/src/context/world_state/plugins_instructions_tests.rs
|
||||
expression: "render_section_cases(&[(Absent, Absent), (Absent, Known(&unavailable)),\n(Absent, Known(&available)), (Known(&unavailable), Known(&available)),\n(Known(&available), Known(&available)),\n(Known(&available), Known(&unavailable)), (Unknown, Known(&unavailable)),\n(Unknown, Known(&available)),])"
|
||||
---
|
||||
Absent -> Absent
|
||||
None
|
||||
|
||||
Absent -> false
|
||||
None
|
||||
|
||||
Absent -> true (role - developer)
|
||||
<plugins_instructions>
|
||||
## Plugins
|
||||
A plugin is a local bundle of skills, MCP servers, and apps.
|
||||
### How to use plugins
|
||||
- Skill naming: If a plugin contributes skills, those skill entries are prefixed with `plugin_name:` in the Skills list.
|
||||
- MCP naming: Plugin-provided MCP tools keep standard MCP identifiers such as `mcp__server__tool`; use tool provenance to tell which plugin they come from.
|
||||
- Trigger rules: If the user explicitly names a plugin, prefer capabilities associated with that plugin for that turn.
|
||||
- Relationship to capabilities: Plugins are not invoked directly. Use their underlying skills, MCP tools, and app tools to help solve the task.
|
||||
- Relevance: Determine what a plugin can help with from explicit user mention or from the plugin-associated skills, MCP tools, and apps exposed elsewhere in this turn.
|
||||
- Missing/blocked: If the user requests a plugin that does not have relevant callable capabilities for the task, say so briefly and continue with the best fallback.
|
||||
</plugins_instructions>
|
||||
|
||||
false -> true (role - developer)
|
||||
<plugins_instructions>
|
||||
## Plugins
|
||||
A plugin is a local bundle of skills, MCP servers, and apps.
|
||||
### How to use plugins
|
||||
- Skill naming: If a plugin contributes skills, those skill entries are prefixed with `plugin_name:` in the Skills list.
|
||||
- MCP naming: Plugin-provided MCP tools keep standard MCP identifiers such as `mcp__server__tool`; use tool provenance to tell which plugin they come from.
|
||||
- Trigger rules: If the user explicitly names a plugin, prefer capabilities associated with that plugin for that turn.
|
||||
- Relationship to capabilities: Plugins are not invoked directly. Use their underlying skills, MCP tools, and app tools to help solve the task.
|
||||
- Relevance: Determine what a plugin can help with from explicit user mention or from the plugin-associated skills, MCP tools, and apps exposed elsewhere in this turn.
|
||||
- Missing/blocked: If the user requests a plugin that does not have relevant callable capabilities for the task, say so briefly and continue with the best fallback.
|
||||
</plugins_instructions>
|
||||
|
||||
true -> true
|
||||
None
|
||||
|
||||
true -> false
|
||||
None
|
||||
|
||||
Unknown -> false
|
||||
None
|
||||
|
||||
Unknown -> true
|
||||
None
|
||||
@@ -0,0 +1,83 @@
|
||||
use super::ErasedWorldStateSection;
|
||||
use super::PreviousSectionState;
|
||||
use super::WorldStateSection;
|
||||
use crate::context::ContextualUserFragment;
|
||||
|
||||
pub(super) fn render_section_cases<'a, S: WorldStateSection>(
|
||||
cases: &[(PreviousSectionState<'a, S>, PreviousSectionState<'a, S>)],
|
||||
) -> String {
|
||||
cases
|
||||
.iter()
|
||||
.map(|(before, after)| {
|
||||
let rendered = render_diff(before, after);
|
||||
let role = rendered.as_ref().map_or_else(String::new, |fragment| {
|
||||
format!(" (role - {})", fragment.role())
|
||||
});
|
||||
let content = rendered
|
||||
.as_ref()
|
||||
.map_or_else(|| "None".to_string(), |fragment| fragment.render());
|
||||
format!(
|
||||
"{} -> {}{role}\n{content}",
|
||||
render_state(before),
|
||||
render_state(after),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n\n")
|
||||
}
|
||||
|
||||
fn render_state<S: WorldStateSection>(state: &PreviousSectionState<'_, S>) -> String {
|
||||
match state {
|
||||
PreviousSectionState::Absent => "Absent".to_string(),
|
||||
PreviousSectionState::Unknown => "Unknown".to_string(),
|
||||
PreviousSectionState::Known(section) => render_snapshot(*section),
|
||||
}
|
||||
}
|
||||
|
||||
fn render_diff<S: WorldStateSection>(
|
||||
before: &PreviousSectionState<'_, S>,
|
||||
after: &PreviousSectionState<'_, S>,
|
||||
) -> Option<Box<dyn ContextualUserFragment>> {
|
||||
let PreviousSectionState::Known(after) = after else {
|
||||
return None;
|
||||
};
|
||||
let previous_snapshot;
|
||||
let previous = match before {
|
||||
PreviousSectionState::Absent => PreviousSectionState::Absent,
|
||||
PreviousSectionState::Unknown => PreviousSectionState::Unknown,
|
||||
PreviousSectionState::Known(before) => {
|
||||
previous_snapshot = snapshot_value(*before);
|
||||
PreviousSectionState::Known(&previous_snapshot)
|
||||
}
|
||||
};
|
||||
ErasedWorldStateSection::render_diff(*after, previous)
|
||||
}
|
||||
|
||||
fn render_snapshot<S: WorldStateSection>(section: &S) -> String {
|
||||
serde_json::to_string(&sort_json(snapshot_value(section)))
|
||||
.expect("world-state section snapshot should serialize")
|
||||
}
|
||||
|
||||
fn sort_json(value: serde_json::Value) -> serde_json::Value {
|
||||
match value {
|
||||
serde_json::Value::Array(values) => {
|
||||
serde_json::Value::Array(values.into_iter().map(sort_json).collect())
|
||||
}
|
||||
serde_json::Value::Object(values) => {
|
||||
let mut values = values.into_iter().collect::<Vec<_>>();
|
||||
values.sort_by(|(left, _), (right, _)| left.cmp(right));
|
||||
serde_json::Value::Object(
|
||||
values
|
||||
.into_iter()
|
||||
.map(|(key, value)| (key, sort_json(value)))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
value => value,
|
||||
}
|
||||
}
|
||||
|
||||
fn snapshot_value<S: WorldStateSection>(section: &S) -> serde_json::Value {
|
||||
ErasedWorldStateSection::snapshot(section)
|
||||
.expect("world-state section snapshot should serialize to a non-null value")
|
||||
}
|
||||
Reference in New Issue
Block a user