mirror of
https://github.com/openai/codex.git
synced 2026-05-01 09:56:37 +00:00
Fix compaction context reinjection and model baselines (#12252)
## Summary - move regular-turn context diff/full-context persistence into `run_turn` so pre-turn compaction runs before incoming context updates are recorded - after successful pre-turn compaction, rely on a cleared `reference_context_item` to trigger full context reinjection on the follow-up regular turn (manual `/compact` keeps replacement history summary-only and also clears the baseline) - preserve `<model_switch>` when full context is reinjected, and inject it *before* the rest of the full-context items - scope `reference_context_item` and `previous_model` to regular user turns only so standalone tasks (`/compact`, shell, review, undo) cannot suppress future reinjection or `<model_switch>` behavior - make context-diff persistence + `reference_context_item` updates explicit in the regular-turn path, with clearer docs/comments around the invariant - stop persisting local `/compact` `RolloutItem::TurnContext` snapshots (only regular turns persist `TurnContextItem` now) - simplify resume/fork previous-model/reference-baseline hydration by looking up the last surviving turn context from rollout lifecycle events, including rollback and compaction-crossing handling - remove the legacy fallback that guessed from bare `TurnContext` rollouts without lifecycle events - update compaction/remote-compaction/model-visible snapshots and compact test assertions (including remote compaction mock response shape) ## Why We were persisting incoming context items before spawning the regular turn task, which let pre-turn compaction requests accidentally include incoming context diffs without the new user message. Fixing that exposed follow-on baseline issues around `/compact`, resume/fork, and standalone tasks that could cause duplicate context injection or suppress `<model_switch>` instructions. This PR re-centers the invariants around regular turns: - regular turns persist model-visible context diffs/full reinjection and update the `reference_context_item` - standalone tasks do not advance those regular-turn baselines - compaction clears the baseline when replacement history may have stripped the referenced context diffs ## Follow-ups (TODOs left in code) - `TODO(ccunningham)`: fix rollback/backtracking baseline handling more comprehensively - `TODO(ccunningham)`: include pending incoming context items in pre-turn compaction threshold estimation - `TODO(ccunningham)`: inject updated personality spec alongside `<model_switch>` so some model-switch paths can avoid forced full reinjection - `TODO(ccunningham)`: review task turn lifecycle (`TurnStarted`/`TurnComplete`) behavior and emit task-start context diffs for task types that should have them (excluding `/compact`) ## Validation - `just fmt` - CI should cover the updated compaction/resume/model-visible snapshot expectations and rollout-hydration behavior - I did **not** rerun the full local test suite after the latest resume-lookup / rollout-persistence simplifications
This commit is contained in:
committed by
GitHub
parent
264fc444b6
commit
bb0ac5be70
@@ -867,7 +867,7 @@ pub async fn mount_compact_json_once(server: &MockServer, body: serde_json::Valu
|
||||
|
||||
/// Mount a `/responses/compact` mock that mirrors the default remote compaction shape:
|
||||
/// keep user+developer messages from the request, drop assistant/tool artifacts, and append one
|
||||
/// summary user message.
|
||||
/// compaction item carrying the provided summary text.
|
||||
pub async fn mount_compact_user_history_with_summary_once(
|
||||
server: &MockServer,
|
||||
summary_text: &str,
|
||||
@@ -911,6 +911,9 @@ pub async fn mount_compact_user_history_with_summary_sequence(
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
// TODO(ccunningham): Update this mock to match future compaction model behavior:
|
||||
// return user/developer/assistant messages since the last compaction item, then
|
||||
// append a single newest compaction item.
|
||||
// Match current remote compaction behavior: keep user/developer messages and
|
||||
// omit assistant/tool history entries.
|
||||
.filter(|item| {
|
||||
@@ -921,11 +924,10 @@ pub async fn mount_compact_user_history_with_summary_sequence(
|
||||
)
|
||||
})
|
||||
.collect::<Vec<Value>>();
|
||||
// Append the synthetic summary message as the newest user item.
|
||||
// Append a synthetic compaction item as the newest item.
|
||||
output.push(serde_json::json!({
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [{"type": "input_text", "text": summary_text}],
|
||||
"type": "compaction",
|
||||
"encrypted_content": summary_text,
|
||||
}));
|
||||
ResponseTemplate::new(200)
|
||||
.insert_header("content-type", "application/json")
|
||||
|
||||
@@ -363,7 +363,7 @@ async fn summarize_context_three_requests_and_instructions() {
|
||||
codex.submit(Op::Shutdown).await.unwrap();
|
||||
wait_for_event(&codex, |ev| matches!(ev, EventMsg::ShutdownComplete)).await;
|
||||
|
||||
// Verify rollout contains APITurn entries for each API call and a Compacted entry.
|
||||
// Verify rollout contains regular sampling TurnContext entries and a Compacted entry.
|
||||
println!("rollout path: {}", rollout_path.display());
|
||||
let text = std::fs::read_to_string(&rollout_path).unwrap_or_else(|e| {
|
||||
panic!(
|
||||
@@ -371,7 +371,7 @@ async fn summarize_context_three_requests_and_instructions() {
|
||||
rollout_path.display()
|
||||
)
|
||||
});
|
||||
let mut api_turn_count = 0usize;
|
||||
let mut regular_turn_context_count = 0usize;
|
||||
let mut saw_compacted_summary = false;
|
||||
for line in text.lines() {
|
||||
let trimmed = line.trim();
|
||||
@@ -383,7 +383,7 @@ async fn summarize_context_three_requests_and_instructions() {
|
||||
};
|
||||
match entry.item {
|
||||
RolloutItem::TurnContext(_) => {
|
||||
api_turn_count += 1;
|
||||
regular_turn_context_count += 1;
|
||||
}
|
||||
RolloutItem::Compacted(ci) => {
|
||||
if ci.message == expected_summary_message {
|
||||
@@ -395,8 +395,8 @@ async fn summarize_context_three_requests_and_instructions() {
|
||||
}
|
||||
|
||||
assert!(
|
||||
api_turn_count == 3,
|
||||
"expected three APITurn entries in rollout"
|
||||
regular_turn_context_count == 2,
|
||||
"expected two regular sampling TurnContext entries in rollout"
|
||||
);
|
||||
assert!(
|
||||
saw_compacted_summary,
|
||||
@@ -2414,26 +2414,36 @@ async fn manual_compact_twice_preserves_latest_user_messages() {
|
||||
first_request_user_texts[first_turn_user_index], first_user_message,
|
||||
"first turn request should end with the submitted user message"
|
||||
);
|
||||
let seeded_user_prefix = &first_request_user_texts[..first_turn_user_index];
|
||||
let initial_seeded_user_prefix = &first_request_user_texts[..first_turn_user_index];
|
||||
|
||||
let final_request_user_texts = requests
|
||||
.last()
|
||||
.unwrap_or_else(|| panic!("final turn request missing for {final_user_message}"))
|
||||
.message_input_texts("user");
|
||||
assert!(
|
||||
final_request_user_texts
|
||||
.as_slice()
|
||||
.starts_with(seeded_user_prefix),
|
||||
"final request should start with seeded user prefix from first request: {seeded_user_prefix:?}"
|
||||
!initial_seeded_user_prefix.is_empty(),
|
||||
"first turn should include seeded user prefix before the submitted user message"
|
||||
);
|
||||
let final_output = &final_request_user_texts[seeded_user_prefix.len()..];
|
||||
let expected = vec![
|
||||
let (final_request_last_user_text, final_request_before_last_user) = final_request_user_texts
|
||||
.split_last()
|
||||
.unwrap_or_else(|| panic!("final turn request missing user messages"));
|
||||
assert_eq!(
|
||||
final_request_last_user_text, final_user_message,
|
||||
"final turn request should end with the submitted user message"
|
||||
);
|
||||
let history_before_seeded_prefix = final_request_before_last_user
|
||||
.strip_suffix(initial_seeded_user_prefix)
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"final request should end with the seeded user prefix from the first request: {initial_seeded_user_prefix:?}"
|
||||
)
|
||||
});
|
||||
let expected_history = vec![
|
||||
first_user_message.to_string(),
|
||||
second_user_message.to_string(),
|
||||
expected_second_summary,
|
||||
final_user_message.to_string(),
|
||||
];
|
||||
assert_eq!(final_output, expected.as_slice());
|
||||
assert_eq!(history_before_seeded_prefix, expected_history.as_slice());
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
|
||||
@@ -93,12 +93,9 @@ async fn remote_compact_replaces_history_for_followups() -> Result<()> {
|
||||
)
|
||||
.await;
|
||||
|
||||
let compacted_history = vec![
|
||||
responses::user_message_item("REMOTE_COMPACTED_SUMMARY"),
|
||||
ResponseItem::Compaction {
|
||||
encrypted_content: "ENCRYPTED_COMPACTION_SUMMARY".to_string(),
|
||||
},
|
||||
];
|
||||
let compacted_history = vec![ResponseItem::Compaction {
|
||||
encrypted_content: "ENCRYPTED_COMPACTION_SUMMARY".to_string(),
|
||||
}];
|
||||
let compact_mock = responses::mount_compact_json_once(
|
||||
harness.server(),
|
||||
serde_json::json!({ "output": compacted_history.clone() }),
|
||||
@@ -159,7 +156,7 @@ async fn remote_compact_replaces_history_for_followups() -> Result<()> {
|
||||
let follow_up_request = response_requests.last().expect("follow-up request missing");
|
||||
let follow_up_body = follow_up_request.body_json().to_string();
|
||||
assert!(
|
||||
follow_up_body.contains("REMOTE_COMPACTED_SUMMARY"),
|
||||
follow_up_body.contains("\"type\":\"compaction\""),
|
||||
"expected follow-up request to use compacted history"
|
||||
);
|
||||
assert!(
|
||||
@@ -178,7 +175,7 @@ async fn remote_compact_replaces_history_for_followups() -> Result<()> {
|
||||
insta::assert_snapshot!(
|
||||
"remote_manual_compact_with_history_shapes",
|
||||
format_labeled_requests_snapshot(
|
||||
"Remote manual /compact where remote compact output is summary-only: follow-up layout uses returned summary plus new user message.",
|
||||
"Remote manual /compact where remote compact output is compaction-only: follow-up layout uses the returned compaction item plus new user message.",
|
||||
&[
|
||||
("Remote Compaction Request", &compact_request),
|
||||
("Remote Post-Compaction History Layout", follow_up_request),
|
||||
@@ -958,7 +955,6 @@ async fn remote_compact_persists_replacement_history_in_rollout() -> Result<()>
|
||||
.await;
|
||||
|
||||
let compacted_history = vec![
|
||||
responses::user_message_item("COMPACTED_USER_SUMMARY"),
|
||||
ResponseItem::Compaction {
|
||||
encrypted_content: "ENCRYPTED_COMPACTION_SUMMARY".to_string(),
|
||||
},
|
||||
@@ -1012,17 +1008,6 @@ async fn remote_compact_persists_replacement_history_in_rollout() -> Result<()>
|
||||
&& compacted.message.is_empty()
|
||||
&& let Some(replacement_history) = compacted.replacement_history.as_ref()
|
||||
{
|
||||
let has_compacted_user_summary = replacement_history.iter().any(|item| {
|
||||
matches!(
|
||||
item,
|
||||
ResponseItem::Message { role, content, .. }
|
||||
if role == "user"
|
||||
&& content.iter().any(|part| matches!(
|
||||
part,
|
||||
ContentItem::InputText { text } if text == "COMPACTED_USER_SUMMARY"
|
||||
))
|
||||
)
|
||||
});
|
||||
let has_compaction_item = replacement_history.iter().any(|item| {
|
||||
matches!(
|
||||
item,
|
||||
@@ -1054,7 +1039,7 @@ async fn remote_compact_persists_replacement_history_in_rollout() -> Result<()>
|
||||
)
|
||||
});
|
||||
|
||||
if has_compacted_user_summary && has_compaction_item && has_compacted_assistant_note {
|
||||
if has_compaction_item && has_compacted_assistant_note {
|
||||
assert!(
|
||||
!has_permissions_developer_message,
|
||||
"manual remote compact rollout replacement history should not inject permissions context"
|
||||
@@ -1110,7 +1095,6 @@ async fn remote_compact_and_resume_refresh_stale_developer_instructions() -> Res
|
||||
.await;
|
||||
|
||||
let compacted_history = vec![
|
||||
responses::user_message_item("REMOTE_COMPACTED_SUMMARY"),
|
||||
ResponseItem::Message {
|
||||
id: None,
|
||||
role: "developer".to_string(),
|
||||
@@ -1196,8 +1180,8 @@ async fn remote_compact_and_resume_refresh_stale_developer_instructions() -> Res
|
||||
"fresh developer instructions should be present after compaction"
|
||||
);
|
||||
assert!(
|
||||
after_compact_body.contains("REMOTE_COMPACTED_SUMMARY"),
|
||||
"compacted summary should be present after compaction"
|
||||
after_compact_body.contains("ENCRYPTED_COMPACTION_SUMMARY"),
|
||||
"compaction item should be present after compaction"
|
||||
);
|
||||
|
||||
let after_resume_body = after_resume_request.body_json().to_string();
|
||||
@@ -1210,8 +1194,8 @@ async fn remote_compact_and_resume_refresh_stale_developer_instructions() -> Res
|
||||
"fresh developer instructions should be present after resume"
|
||||
);
|
||||
assert!(
|
||||
after_resume_body.contains("REMOTE_COMPACTED_SUMMARY"),
|
||||
"compacted summary should persist after resume"
|
||||
after_resume_body.contains("ENCRYPTED_COMPACTION_SUMMARY"),
|
||||
"compaction item should persist after resume"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
@@ -1243,7 +1227,6 @@ async fn remote_compact_refreshes_stale_developer_instructions_without_resume()
|
||||
.await;
|
||||
|
||||
let compacted_history = vec![
|
||||
responses::user_message_item("REMOTE_COMPACTED_SUMMARY"),
|
||||
ResponseItem::Message {
|
||||
id: None,
|
||||
role: "developer".to_string(),
|
||||
@@ -1302,8 +1285,8 @@ async fn remote_compact_refreshes_stale_developer_instructions_without_resume()
|
||||
"fresh developer instructions should be present after compaction"
|
||||
);
|
||||
assert!(
|
||||
after_compact_body.contains("REMOTE_COMPACTED_SUMMARY"),
|
||||
"compacted summary should be present after compaction"
|
||||
after_compact_body.contains("ENCRYPTED_COMPACTION_SUMMARY"),
|
||||
"compaction item should be present after compaction"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
@@ -1706,7 +1689,7 @@ async fn snapshot_request_shape_remote_mid_turn_continuation_compaction() -> Res
|
||||
insta::assert_snapshot!(
|
||||
"remote_mid_turn_compaction_shapes",
|
||||
format_labeled_requests_snapshot(
|
||||
"Remote mid-turn continuation compaction after tool output: compact request includes tool artifacts and follow-up request includes the summary.",
|
||||
"Remote mid-turn continuation compaction after tool output: compact request includes tool artifacts and the follow-up request includes the returned compaction item.",
|
||||
&[
|
||||
("Remote Compaction Request", &compact_request),
|
||||
("Remote Post-Compaction History Layout", &requests[1]),
|
||||
@@ -1749,9 +1732,9 @@ async fn snapshot_request_shape_remote_mid_turn_compaction_summary_only_reinject
|
||||
)
|
||||
.await;
|
||||
|
||||
let compacted_history = vec![responses::user_message_item(&summary_with_prefix(
|
||||
"REMOTE_SUMMARY_ONLY",
|
||||
))];
|
||||
let compacted_history = vec![ResponseItem::Compaction {
|
||||
encrypted_content: summary_with_prefix("REMOTE_SUMMARY_ONLY"),
|
||||
}];
|
||||
let compact_mock = responses::mount_compact_json_once(
|
||||
harness.server(),
|
||||
serde_json::json!({ "output": compacted_history }),
|
||||
@@ -1786,7 +1769,7 @@ async fn snapshot_request_shape_remote_mid_turn_compaction_summary_only_reinject
|
||||
insta::assert_snapshot!(
|
||||
"remote_mid_turn_compaction_summary_only_reinjects_context_shapes",
|
||||
format_labeled_requests_snapshot(
|
||||
"Remote mid-turn compaction where compact output has only summary user content: continuation layout reinjects canonical context before that summary.",
|
||||
"Remote mid-turn compaction where compact output has only a compaction item: continuation layout reinjects context before that compaction item.",
|
||||
&[
|
||||
("Remote Compaction Request", &compact_request),
|
||||
(
|
||||
@@ -1893,13 +1876,13 @@ async fn snapshot_request_shape_remote_mid_turn_compaction_multi_summary_reinjec
|
||||
insta::assert_snapshot!(
|
||||
"remote_mid_turn_compaction_multi_summary_reinjects_above_last_summary_shapes",
|
||||
format_labeled_requests_snapshot(
|
||||
"Remote mid-turn compaction after an earlier summary compaction: the older summary remains in model-visible history and round-trips into the next compact request.",
|
||||
"After a prior manual /compact produced an older remote compaction item, the next turn hits remote auto-compaction before the next sampling request. The compact request carries forward that earlier compaction item, and the next sampling request shows the latest compaction item with context reinjected before USER_TWO.",
|
||||
&[
|
||||
("Remote Compaction Request", &compact_request),
|
||||
(
|
||||
"Second Turn Request (Before Mid-Turn Compaction)",
|
||||
"Second Turn Request (After Compaction)",
|
||||
&second_turn_request
|
||||
),
|
||||
("Remote Compaction Request", &compact_request),
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
@@ -81,25 +81,32 @@ fn normalize_line_endings_str(text: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_summary_message(request: &Value, summary_text: &str) -> Value {
|
||||
fn extract_summary_user_text(request: &Value, summary_text: &str) -> String {
|
||||
json_message_input_texts(request, "user")
|
||||
.into_iter()
|
||||
.find(|text| text.contains(summary_text))
|
||||
.unwrap_or_else(|| panic!("expected summary message {summary_text}"))
|
||||
}
|
||||
|
||||
fn json_message_input_texts(request: &Value, role: &str) -> Vec<String> {
|
||||
request
|
||||
.get("input")
|
||||
.and_then(Value::as_array)
|
||||
.and_then(|items| {
|
||||
items.iter().find(|item| {
|
||||
item.get("type").and_then(Value::as_str) == Some("message")
|
||||
&& item.get("role").and_then(Value::as_str) == Some("user")
|
||||
&& item
|
||||
.get("content")
|
||||
.and_then(Value::as_array)
|
||||
.and_then(|arr| arr.first())
|
||||
.and_then(|entry| entry.get("text"))
|
||||
.and_then(Value::as_str)
|
||||
.is_some_and(|text| text.contains(summary_text))
|
||||
})
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter(|item| {
|
||||
item.get("type").and_then(Value::as_str) == Some("message")
|
||||
&& item.get("role").and_then(Value::as_str) == Some(role)
|
||||
})
|
||||
.cloned()
|
||||
.unwrap_or_else(|| panic!("expected summary message {summary_text}"))
|
||||
.filter_map(|item| {
|
||||
item.get("content")
|
||||
.and_then(Value::as_array)
|
||||
.and_then(|content| content.first())
|
||||
.and_then(|entry| entry.get("text"))
|
||||
.and_then(Value::as_str)
|
||||
.map(str::to_string)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn normalize_compact_prompts(requests: &mut [Value]) {
|
||||
@@ -200,459 +207,88 @@ async fn compact_resume_and_fork_preserve_model_history_view() {
|
||||
&fork_arr[..compact_arr.len()]
|
||||
);
|
||||
|
||||
let expected_model = requests[0]["model"]
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
let prompt = requests[0]["instructions"]
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
let permissions_message = requests[0]["input"][0].clone();
|
||||
let user_instructions = requests[0]["input"][1]["content"][0]["text"]
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
let environment_context = requests[0]["input"][2]["content"][0]["text"]
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
let tool_calls = json!(requests[0]["tools"].as_array());
|
||||
let prompt_cache_key = requests[0]["prompt_cache_key"]
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
let fork_prompt_cache_key = requests[requests.len() - 1]["prompt_cache_key"]
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
let summary_after_compact = extract_summary_message(&requests[2], SUMMARY_TEXT);
|
||||
let summary_after_resume = extract_summary_message(&requests[3], SUMMARY_TEXT);
|
||||
let summary_after_fork = extract_summary_message(&requests[4], SUMMARY_TEXT);
|
||||
let user_turn_1 = json!(
|
||||
{
|
||||
"model": expected_model,
|
||||
"instructions": prompt,
|
||||
"input": [
|
||||
permissions_message,
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": user_instructions
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": environment_context
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "hello world"
|
||||
}
|
||||
]
|
||||
let first_request_user_texts = json_message_input_texts(&requests[0], "user");
|
||||
let first_turn_user_index = first_request_user_texts
|
||||
.len()
|
||||
.checked_sub(1)
|
||||
.unwrap_or_else(|| panic!("first turn request missing user messages"));
|
||||
assert_eq!(
|
||||
first_request_user_texts[first_turn_user_index],
|
||||
"hello world"
|
||||
);
|
||||
let seeded_user_prefix = &first_request_user_texts[..first_turn_user_index];
|
||||
let summary_after_compact = extract_summary_user_text(&requests[2], SUMMARY_TEXT);
|
||||
let summary_after_resume = extract_summary_user_text(&requests[3], SUMMARY_TEXT);
|
||||
let summary_after_fork = extract_summary_user_text(&requests[4], SUMMARY_TEXT);
|
||||
let mut expected_after_compact_user_texts =
|
||||
vec!["hello world".to_string(), summary_after_compact];
|
||||
expected_after_compact_user_texts.extend_from_slice(seeded_user_prefix);
|
||||
expected_after_compact_user_texts.push("AFTER_COMPACT".to_string());
|
||||
assert_eq!(
|
||||
json_message_input_texts(&requests[2], "user"),
|
||||
expected_after_compact_user_texts
|
||||
);
|
||||
|
||||
let mut expected_after_resume_user_texts =
|
||||
vec!["hello world".to_string(), summary_after_resume];
|
||||
expected_after_resume_user_texts.extend_from_slice(seeded_user_prefix);
|
||||
expected_after_resume_user_texts.push("AFTER_COMPACT".to_string());
|
||||
let after_resume_user_texts = json_message_input_texts(&requests[3], "user");
|
||||
let (after_resume_last, after_resume_prefix) = after_resume_user_texts
|
||||
.split_last()
|
||||
.unwrap_or_else(|| panic!("after-resume request missing user messages"));
|
||||
assert_eq!(after_resume_last, "AFTER_RESUME");
|
||||
assert!(
|
||||
after_resume_prefix.starts_with(&expected_after_resume_user_texts),
|
||||
"after-resume user texts should preserve compacted history prefix"
|
||||
);
|
||||
let after_resume_seeded_suffix = &after_resume_prefix[expected_after_resume_user_texts.len()..];
|
||||
if seeded_user_prefix.is_empty() {
|
||||
assert!(
|
||||
after_resume_seeded_suffix.is_empty(),
|
||||
"after-resume request should not append unexpected user prefix items"
|
||||
);
|
||||
} else {
|
||||
let mut chunks = after_resume_seeded_suffix.chunks_exact(seeded_user_prefix.len());
|
||||
assert!(
|
||||
chunks.remainder().is_empty(),
|
||||
"after-resume suffix should be whole seeded-prefix repeats"
|
||||
);
|
||||
for chunk in &mut chunks {
|
||||
assert_eq!(chunk, seeded_user_prefix);
|
||||
}
|
||||
],
|
||||
"tools": tool_calls,
|
||||
"tool_choice": "auto",
|
||||
"parallel_tool_calls": false,
|
||||
"reasoning": {
|
||||
"effort": "medium",
|
||||
"summary": "auto"
|
||||
},
|
||||
"store": false,
|
||||
"stream": true,
|
||||
"include": [
|
||||
"reasoning.encrypted_content"
|
||||
],
|
||||
"prompt_cache_key": prompt_cache_key
|
||||
});
|
||||
let compact_1 = json!(
|
||||
{
|
||||
"model": expected_model,
|
||||
"instructions": prompt,
|
||||
"input": [
|
||||
permissions_message,
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": user_instructions
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": environment_context
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "hello world"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "assistant",
|
||||
"content": [
|
||||
{
|
||||
"type": "output_text",
|
||||
"text": "FIRST_REPLY"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": SUMMARIZATION_PROMPT
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
let after_fork_user_texts = json_message_input_texts(&requests[4], "user");
|
||||
let mut expected_after_fork_history_prefix =
|
||||
vec!["hello world".to_string(), summary_after_fork];
|
||||
expected_after_fork_history_prefix.extend_from_slice(seeded_user_prefix);
|
||||
expected_after_fork_history_prefix.push("AFTER_COMPACT".to_string());
|
||||
let (after_fork_last, after_fork_prefix) = after_fork_user_texts
|
||||
.split_last()
|
||||
.unwrap_or_else(|| panic!("after-fork request missing user messages"));
|
||||
assert_eq!(after_fork_last, "AFTER_FORK");
|
||||
assert!(
|
||||
after_fork_prefix.starts_with(&expected_after_fork_history_prefix),
|
||||
"after-fork user texts should preserve compacted user history prefix"
|
||||
);
|
||||
let after_fork_seeded_suffix = &after_fork_prefix[expected_after_fork_history_prefix.len()..];
|
||||
if seeded_user_prefix.is_empty() {
|
||||
assert!(
|
||||
after_fork_seeded_suffix.is_empty(),
|
||||
"after-fork request should not append unexpected user prefix items"
|
||||
);
|
||||
} else {
|
||||
let mut chunks = after_fork_seeded_suffix.chunks_exact(seeded_user_prefix.len());
|
||||
assert!(
|
||||
chunks.remainder().is_empty(),
|
||||
"after-fork suffix should be whole seeded-prefix repeats"
|
||||
);
|
||||
for chunk in &mut chunks {
|
||||
assert_eq!(chunk, seeded_user_prefix);
|
||||
}
|
||||
],
|
||||
"tools": [],
|
||||
"tool_choice": "auto",
|
||||
"parallel_tool_calls": false,
|
||||
"reasoning": {
|
||||
"effort": "medium",
|
||||
"summary": "auto"
|
||||
},
|
||||
"store": false,
|
||||
"stream": true,
|
||||
"include": [
|
||||
"reasoning.encrypted_content"
|
||||
],
|
||||
"prompt_cache_key": prompt_cache_key
|
||||
});
|
||||
let user_turn_2_after_compact = json!(
|
||||
{
|
||||
"model": expected_model,
|
||||
"instructions": prompt,
|
||||
"input": [
|
||||
permissions_message,
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": user_instructions
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": environment_context
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "hello world"
|
||||
}
|
||||
]
|
||||
},
|
||||
summary_after_compact,
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "AFTER_COMPACT"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"tools": tool_calls,
|
||||
"tool_choice": "auto",
|
||||
"parallel_tool_calls": false,
|
||||
"reasoning": {
|
||||
"effort": "medium",
|
||||
"summary": "auto"
|
||||
},
|
||||
"store": false,
|
||||
"stream": true,
|
||||
"include": [
|
||||
"reasoning.encrypted_content"
|
||||
],
|
||||
"prompt_cache_key": prompt_cache_key
|
||||
});
|
||||
let usert_turn_3_after_resume = json!(
|
||||
{
|
||||
"model": expected_model,
|
||||
"instructions": prompt,
|
||||
"input": [
|
||||
permissions_message,
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": user_instructions
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": environment_context
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "hello world"
|
||||
}
|
||||
]
|
||||
},
|
||||
summary_after_resume,
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "AFTER_COMPACT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "assistant",
|
||||
"content": [
|
||||
{
|
||||
"type": "output_text",
|
||||
"text": "AFTER_COMPACT_REPLY"
|
||||
}
|
||||
]
|
||||
},
|
||||
permissions_message,
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": user_instructions
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": environment_context
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "AFTER_RESUME"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"tools": tool_calls,
|
||||
"tool_choice": "auto",
|
||||
"parallel_tool_calls": false,
|
||||
"reasoning": {
|
||||
"effort": "medium",
|
||||
"summary": "auto"
|
||||
},
|
||||
"store": false,
|
||||
"stream": true,
|
||||
"include": [
|
||||
"reasoning.encrypted_content"
|
||||
],
|
||||
"prompt_cache_key": prompt_cache_key
|
||||
});
|
||||
let user_turn_3_after_fork = json!(
|
||||
{
|
||||
"model": expected_model,
|
||||
"instructions": prompt,
|
||||
"input": [
|
||||
permissions_message,
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": user_instructions
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": environment_context
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "hello world"
|
||||
}
|
||||
]
|
||||
},
|
||||
summary_after_fork,
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "AFTER_COMPACT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "assistant",
|
||||
"content": [
|
||||
{
|
||||
"type": "output_text",
|
||||
"text": "AFTER_COMPACT_REPLY"
|
||||
}
|
||||
]
|
||||
},
|
||||
permissions_message,
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": user_instructions
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": environment_context
|
||||
}
|
||||
]
|
||||
},
|
||||
permissions_message,
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": user_instructions
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": environment_context
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "AFTER_FORK"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"tools": tool_calls,
|
||||
"tool_choice": "auto",
|
||||
"parallel_tool_calls": false,
|
||||
"reasoning": {
|
||||
"effort": "medium",
|
||||
"summary": "auto"
|
||||
},
|
||||
"store": false,
|
||||
"stream": true,
|
||||
"include": [
|
||||
"reasoning.encrypted_content"
|
||||
],
|
||||
"prompt_cache_key": fork_prompt_cache_key
|
||||
});
|
||||
let mut expected = json!([
|
||||
user_turn_1,
|
||||
compact_1,
|
||||
user_turn_2_after_compact,
|
||||
usert_turn_3_after_resume,
|
||||
user_turn_3_after_fork
|
||||
]);
|
||||
normalize_line_endings(&mut expected);
|
||||
if let Some(arr) = expected.as_array_mut() {
|
||||
normalize_compact_prompts(arr);
|
||||
}
|
||||
assert_eq!(requests.len(), 5);
|
||||
assert_eq!(json!(requests), expected);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
@@ -725,118 +361,47 @@ async fn compact_resume_after_second_compaction_preserves_history() {
|
||||
compact_filtered.as_slice(),
|
||||
&resume_filtered[..compact_filtered.len()]
|
||||
);
|
||||
// hard coded test
|
||||
let prompt = requests[0]["instructions"]
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
let permissions_message = requests[0]["input"][0].clone();
|
||||
let user_instructions = requests[0]["input"][1]["content"][0]["text"]
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
let environment_instructions = requests[0]["input"][2]["content"][0]["text"]
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
|
||||
// Build expected final request input: initial context + forked user message +
|
||||
// compacted summary + post-compact user message + resumed user message.
|
||||
let first_request_user_texts = json_message_input_texts(&requests[0], "user");
|
||||
let first_turn_user_index = first_request_user_texts
|
||||
.len()
|
||||
.checked_sub(1)
|
||||
.unwrap_or_else(|| panic!("first turn request missing user messages"));
|
||||
assert_eq!(
|
||||
first_request_user_texts[first_turn_user_index],
|
||||
"hello world"
|
||||
);
|
||||
let seeded_user_prefix = &first_request_user_texts[..first_turn_user_index];
|
||||
let summary_after_second_compact =
|
||||
extract_summary_message(&requests[requests.len() - 3], SUMMARY_TEXT);
|
||||
|
||||
let mut expected = json!([
|
||||
{
|
||||
"instructions": prompt,
|
||||
"input": [
|
||||
permissions_message,
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": user_instructions
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": environment_instructions
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "AFTER_FORK"
|
||||
}
|
||||
]
|
||||
},
|
||||
summary_after_second_compact,
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "AFTER_COMPACT_2"
|
||||
}
|
||||
]
|
||||
},
|
||||
permissions_message,
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": user_instructions
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": environment_instructions
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "AFTER_SECOND_RESUME"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
}
|
||||
]);
|
||||
normalize_line_endings(&mut expected);
|
||||
let mut last_request_after_2_compacts = json!([{
|
||||
"instructions": requests[requests.len() -1]["instructions"],
|
||||
"input": requests[requests.len() -1]["input"],
|
||||
}]);
|
||||
if let Some(arr) = expected.as_array_mut() {
|
||||
normalize_compact_prompts(arr);
|
||||
extract_summary_user_text(&requests[requests.len() - 3], SUMMARY_TEXT);
|
||||
let mut expected_after_second_compact_user_texts =
|
||||
vec!["AFTER_FORK".to_string(), summary_after_second_compact];
|
||||
expected_after_second_compact_user_texts.extend_from_slice(seeded_user_prefix);
|
||||
expected_after_second_compact_user_texts.push("AFTER_COMPACT_2".to_string());
|
||||
let final_user_texts = json_message_input_texts(&requests[requests.len() - 1], "user");
|
||||
let (final_last, final_prefix) = final_user_texts
|
||||
.split_last()
|
||||
.unwrap_or_else(|| panic!("after-second-resume request missing user messages"));
|
||||
assert_eq!(final_last, AFTER_SECOND_RESUME);
|
||||
assert!(
|
||||
final_prefix.starts_with(&expected_after_second_compact_user_texts),
|
||||
"after-second-resume user texts should preserve post-compact user history prefix"
|
||||
);
|
||||
let final_seeded_suffix = &final_prefix[expected_after_second_compact_user_texts.len()..];
|
||||
if seeded_user_prefix.is_empty() {
|
||||
assert!(
|
||||
final_seeded_suffix.is_empty(),
|
||||
"after-second-resume request should not append unexpected user prefix items"
|
||||
);
|
||||
} else {
|
||||
let mut chunks = final_seeded_suffix.chunks_exact(seeded_user_prefix.len());
|
||||
assert!(
|
||||
chunks.remainder().is_empty(),
|
||||
"after-second-resume suffix should be whole seeded-prefix repeats"
|
||||
);
|
||||
for chunk in &mut chunks {
|
||||
assert_eq!(chunk, seeded_user_prefix);
|
||||
}
|
||||
}
|
||||
if let Some(arr) = last_request_after_2_compacts.as_array_mut() {
|
||||
normalize_compact_prompts(arr);
|
||||
}
|
||||
assert_eq!(expected, last_request_after_2_compacts);
|
||||
}
|
||||
|
||||
fn normalize_line_endings(value: &mut Value) {
|
||||
|
||||
@@ -308,6 +308,8 @@ async fn snapshot_model_visible_layout_resume_with_personality_change() -> Resul
|
||||
config.personality = Some(Personality::Pragmatic);
|
||||
});
|
||||
let resumed = resume_builder.resume(&server, home, rollout_path).await?;
|
||||
let resume_override_cwd = resumed.cwd_path().join(PRETURN_CONTEXT_DIFF_CWD);
|
||||
fs::create_dir_all(&resume_override_cwd)?;
|
||||
resumed
|
||||
.codex
|
||||
.submit(Op::UserTurn {
|
||||
@@ -316,7 +318,7 @@ async fn snapshot_model_visible_layout_resume_with_personality_change() -> Resul
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
final_output_json_schema: None,
|
||||
cwd: resumed.cwd_path().to_path_buf(),
|
||||
cwd: resume_override_cwd,
|
||||
approval_policy: AskForApproval::Never,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
model: resumed.session_configured.model.clone(),
|
||||
@@ -398,10 +400,12 @@ async fn snapshot_model_visible_layout_resume_override_matches_rollout_model() -
|
||||
config.model = Some("gpt-5.2-codex".to_string());
|
||||
});
|
||||
let resumed = resume_builder.resume(&server, home, rollout_path).await?;
|
||||
let resume_override_cwd = resumed.cwd_path().join(PRETURN_CONTEXT_DIFF_CWD);
|
||||
fs::create_dir_all(&resume_override_cwd)?;
|
||||
resumed
|
||||
.codex
|
||||
.submit(Op::OverrideTurnContext {
|
||||
cwd: None,
|
||||
cwd: Some(resume_override_cwd),
|
||||
approval_policy: None,
|
||||
sandbox_policy: None,
|
||||
windows_sandbox_level: None,
|
||||
|
||||
@@ -672,12 +672,7 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res
|
||||
});
|
||||
let expected_permissions_msg = body1["input"][0].clone();
|
||||
let body1_input = body1["input"].as_array().expect("input array");
|
||||
let expected_permissions_msg_2 = body2["input"][body1_input.len() + 1].clone();
|
||||
assert_ne!(
|
||||
expected_permissions_msg_2, expected_permissions_msg,
|
||||
"expected updated permissions message after per-turn override"
|
||||
);
|
||||
let expected_model_switch_msg = body2["input"][body1_input.len() + 2].clone();
|
||||
let expected_model_switch_msg = body2["input"][body1_input.len()].clone();
|
||||
assert_eq!(
|
||||
expected_model_switch_msg["role"].as_str(),
|
||||
Some("developer")
|
||||
@@ -688,10 +683,15 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res
|
||||
.is_some_and(|text| text.contains("<model_switch>")),
|
||||
"expected model switch message after model override: {expected_model_switch_msg:?}"
|
||||
);
|
||||
let expected_permissions_msg_2 = body2["input"][body1_input.len() + 2].clone();
|
||||
assert_ne!(
|
||||
expected_permissions_msg_2, expected_permissions_msg,
|
||||
"expected updated permissions message after per-turn override"
|
||||
);
|
||||
let mut expected_body2 = body1_input.to_vec();
|
||||
expected_body2.push(expected_model_switch_msg);
|
||||
expected_body2.push(expected_env_msg_2);
|
||||
expected_body2.push(expected_permissions_msg_2);
|
||||
expected_body2.push(expected_model_switch_msg);
|
||||
expected_body2.push(expected_user_message_2);
|
||||
assert_eq!(body2["input"], serde_json::Value::Array(expected_body2));
|
||||
|
||||
@@ -900,12 +900,7 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu
|
||||
assert_eq!(body1["input"], expected_input_1);
|
||||
|
||||
let body1_input = body1["input"].as_array().expect("input array");
|
||||
let expected_permissions_msg_2 = body2["input"][body1_input.len()].clone();
|
||||
assert_ne!(
|
||||
expected_permissions_msg_2, expected_permissions_msg,
|
||||
"expected updated permissions message after policy change"
|
||||
);
|
||||
let expected_model_switch_msg = body2["input"][body1_input.len() + 1].clone();
|
||||
let expected_model_switch_msg = body2["input"][body1_input.len()].clone();
|
||||
assert_eq!(
|
||||
expected_model_switch_msg["role"].as_str(),
|
||||
Some("developer")
|
||||
@@ -916,14 +911,19 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu
|
||||
.is_some_and(|text| text.contains("<model_switch>")),
|
||||
"expected model switch message after model override: {expected_model_switch_msg:?}"
|
||||
);
|
||||
let expected_permissions_msg_2 = body2["input"][body1_input.len() + 1].clone();
|
||||
assert_ne!(
|
||||
expected_permissions_msg_2, expected_permissions_msg,
|
||||
"expected updated permissions message after policy change"
|
||||
);
|
||||
let expected_user_message_2 = text_user_input("hello 2".to_string());
|
||||
let expected_input_2 = serde_json::Value::Array(vec![
|
||||
expected_permissions_msg,
|
||||
expected_ui_msg,
|
||||
expected_env_msg_1,
|
||||
expected_user_message_1,
|
||||
expected_permissions_msg_2,
|
||||
expected_model_switch_msg,
|
||||
expected_permissions_msg_2,
|
||||
expected_user_message_2,
|
||||
]);
|
||||
assert_eq!(body2["input"], expected_input_2);
|
||||
|
||||
@@ -6,9 +6,13 @@ use codex_core::protocol::EventMsg;
|
||||
use codex_core::protocol::InitialHistory;
|
||||
use codex_core::protocol::ResumedHistory;
|
||||
use codex_core::protocol::RolloutItem;
|
||||
use codex_core::protocol::TurnCompleteEvent;
|
||||
use codex_core::protocol::TurnContextItem;
|
||||
use codex_core::protocol::TurnStartedEvent;
|
||||
use codex_core::protocol::UserMessageEvent;
|
||||
use codex_core::protocol::WarningEvent;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
use core::time::Duration;
|
||||
use core_test_support::load_default_config_for_test;
|
||||
use core_test_support::wait_for_event;
|
||||
@@ -19,8 +23,9 @@ fn resume_history(
|
||||
previous_model: &str,
|
||||
rollout_path: &std::path::Path,
|
||||
) -> InitialHistory {
|
||||
let turn_id = "resume-warning-seed-turn".to_string();
|
||||
let turn_ctx = TurnContextItem {
|
||||
turn_id: None,
|
||||
turn_id: Some(turn_id.clone()),
|
||||
cwd: config.cwd.clone(),
|
||||
approval_policy: config.permissions.approval_policy.value(),
|
||||
sandbox_policy: config.permissions.sandbox_policy.get().clone(),
|
||||
@@ -38,7 +43,24 @@ fn resume_history(
|
||||
|
||||
InitialHistory::Resumed(ResumedHistory {
|
||||
conversation_id: ThreadId::default(),
|
||||
history: vec![RolloutItem::TurnContext(turn_ctx)],
|
||||
history: vec![
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(TurnStartedEvent {
|
||||
turn_id: turn_id.clone(),
|
||||
model_context_window: None,
|
||||
collaboration_mode_kind: ModeKind::Default,
|
||||
})),
|
||||
RolloutItem::EventMsg(EventMsg::UserMessage(UserMessageEvent {
|
||||
message: "seed".to_string(),
|
||||
images: None,
|
||||
local_images: vec![],
|
||||
text_elements: vec![],
|
||||
})),
|
||||
RolloutItem::TurnContext(turn_ctx),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id,
|
||||
last_agent_message: None,
|
||||
})),
|
||||
],
|
||||
rollout_path: rollout_path.to_path_buf(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ Scenario: Manual /compact with prior user history compacts existing history and
|
||||
05:message/user:<SUMMARIZATION_PROMPT>
|
||||
|
||||
## Local Post-Compaction History Layout
|
||||
00:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
01:message/user:<AGENTS_MD>
|
||||
02:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
03:message/user:first manual turn
|
||||
04:message/user:<COMPACTION_SUMMARY>\nFIRST_MANUAL_SUMMARY
|
||||
00:message/user:first manual turn
|
||||
01:message/user:<COMPACTION_SUMMARY>\nFIRST_MANUAL_SUMMARY
|
||||
02:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
03:message/user:<AGENTS_MD>
|
||||
04:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
05:message/user:second manual turn
|
||||
|
||||
@@ -11,8 +11,8 @@ Scenario: Manual /compact with no prior user turn currently still issues a compa
|
||||
03:message/user:<SUMMARIZATION_PROMPT>
|
||||
|
||||
## Local Post-Compaction History Layout
|
||||
00:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
01:message/user:<AGENTS_MD>
|
||||
02:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
03:message/user:<COMPACTION_SUMMARY>\nMANUAL_EMPTY_SUMMARY
|
||||
00:message/user:<COMPACTION_SUMMARY>\nMANUAL_EMPTY_SUMMARY
|
||||
01:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
02:message/user:<AGENTS_MD>
|
||||
03:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
04:message/user:AFTER_MANUAL_EMPTY_COMPACT
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: core/tests/suite/compact.rs
|
||||
assertion_line: 1773
|
||||
expression: "format_labeled_requests_snapshot(\"Pre-sampling compaction on model switch to a smaller context window: current behavior compacts using prior-turn history only (incoming user message excluded), and the follow-up request carries compacted history plus the new user message.\",\n&[(\"Initial Request (Previous Model)\", &requests[0]),\n(\"Pre-sampling Compaction Request\", &requests[1]),\n(\"Post-Compaction Follow-up Request (Next Model)\", &requests[2]),])"
|
||||
---
|
||||
Scenario: Pre-sampling compaction on model switch to a smaller context window: current behavior compacts using prior-turn history only (incoming user message excluded), and the follow-up request carries compacted history plus the new user message.
|
||||
@@ -22,10 +21,10 @@ Scenario: Pre-sampling compaction on model switch to a smaller context window: c
|
||||
06:message/user:<SUMMARIZATION_PROMPT>
|
||||
|
||||
## Post-Compaction Follow-up Request (Next Model)
|
||||
00:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
01:message/user:<AGENTS_MD>
|
||||
02:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
03:message/user:before switch
|
||||
04:message/user:<COMPACTION_SUMMARY>\nPRE_SAMPLING_SUMMARY
|
||||
05:message/developer:<model_switch>\nThe user was previously using a different model....
|
||||
00:message/user:before switch
|
||||
01:message/user:<COMPACTION_SUMMARY>\nPRE_SAMPLING_SUMMARY
|
||||
02:message/developer:<model_switch>\nThe user was previously using a different model....
|
||||
03:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
04:message/user:<AGENTS_MD>
|
||||
05:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
06:message/user:after switch
|
||||
|
||||
@@ -12,14 +12,13 @@ Scenario: Pre-turn auto-compaction with a context override emits the context dif
|
||||
04:message/assistant:FIRST_REPLY
|
||||
05:message/user:USER_TWO
|
||||
06:message/assistant:SECOND_REPLY
|
||||
07:message/user:<ENVIRONMENT_CONTEXT:cwd=PRETURN_CONTEXT_DIFF_CWD>
|
||||
08:message/user:<SUMMARIZATION_PROMPT>
|
||||
07:message/user:<SUMMARIZATION_PROMPT>
|
||||
|
||||
## Local Post-Compaction History Layout
|
||||
00:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
01:message/user:<AGENTS_MD>
|
||||
02:message/user:<ENVIRONMENT_CONTEXT:cwd=PRETURN_CONTEXT_DIFF_CWD>
|
||||
03:message/user:USER_ONE
|
||||
04:message/user:USER_TWO
|
||||
05:message/user:<COMPACTION_SUMMARY>\nPRE_TURN_SUMMARY
|
||||
00:message/user:USER_ONE
|
||||
01:message/user:USER_TWO
|
||||
02:message/user:<COMPACTION_SUMMARY>\nPRE_TURN_SUMMARY
|
||||
03:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
04:message/user:<AGENTS_MD>
|
||||
05:message/user:<ENVIRONMENT_CONTEXT:cwd=PRETURN_CONTEXT_DIFF_CWD>
|
||||
06:message/user:<image> | <input_image:image_url> | </image> | USER_THREE
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: core/tests/suite/compact.rs
|
||||
assertion_line: 3152
|
||||
expression: "format_labeled_requests_snapshot(\"Pre-turn compaction during model switch (without pre-sampling model-switch compaction): current behavior strips incoming <model_switch> from the compact request and restores it in the post-compaction follow-up request.\",\n&[(\"Initial Request (Previous Model)\", &requests[0]),\n(\"Local Compaction Request\", &requests[1]),\n(\"Local Post-Compaction History Layout\", &requests[2]),])"
|
||||
---
|
||||
Scenario: Pre-turn compaction during model switch (without pre-sampling model-switch compaction): current behavior strips incoming <model_switch> from the compact request and restores it in the post-compaction follow-up request.
|
||||
@@ -22,11 +21,11 @@ Scenario: Pre-turn compaction during model switch (without pre-sampling model-sw
|
||||
06:message/user:<SUMMARIZATION_PROMPT>
|
||||
|
||||
## Local Post-Compaction History Layout
|
||||
00:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
01:message/developer:<personality_spec> The user has requested a new communication st...
|
||||
02:message/user:<AGENTS_MD>
|
||||
03:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
04:message/user:BEFORE_SWITCH_USER
|
||||
05:message/user:<COMPACTION_SUMMARY>\nPRETURN_SWITCH_SUMMARY
|
||||
06:message/developer:<model_switch>\nThe user was previously using a different model....
|
||||
00:message/user:BEFORE_SWITCH_USER
|
||||
01:message/user:<COMPACTION_SUMMARY>\nPRETURN_SWITCH_SUMMARY
|
||||
02:message/developer:<model_switch>\nThe user was previously using a different model....
|
||||
03:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
04:message/developer:<personality_spec> The user has requested a new communication st...
|
||||
05:message/user:<AGENTS_MD>
|
||||
06:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
07:message/user:AFTER_SWITCH_USER
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
---
|
||||
source: core/tests/suite/compact_remote.rs
|
||||
assertion_line: 178
|
||||
expression: "format_labeled_requests_snapshot(\"Remote manual /compact where remote compact output is summary-only: follow-up layout uses returned summary plus new user message.\",\n&[(\"Remote Compaction Request\", &compact_request),\n(\"Remote Post-Compaction History Layout\", follow_up_request),])"
|
||||
expression: "format_labeled_requests_snapshot(\"Remote manual /compact where remote compact output is compaction-only: follow-up layout uses the returned compaction item plus new user message.\",\n&[(\"Remote Compaction Request\", &compact_request),\n(\"Remote Post-Compaction History Layout\", follow_up_request),])"
|
||||
---
|
||||
Scenario: Remote manual /compact where remote compact output is summary-only: follow-up layout uses returned summary plus new user message.
|
||||
Scenario: Remote manual /compact where remote compact output is compaction-only: follow-up layout uses the returned compaction item plus new user message.
|
||||
|
||||
## Remote Compaction Request
|
||||
00:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
@@ -13,9 +12,8 @@ Scenario: Remote manual /compact where remote compact output is summary-only: fo
|
||||
04:message/assistant:FIRST_REMOTE_REPLY
|
||||
|
||||
## Remote Post-Compaction History Layout
|
||||
00:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
01:message/user:<AGENTS_MD>
|
||||
02:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
03:message/user:REMOTE_COMPACTED_SUMMARY
|
||||
04:compaction:encrypted=true
|
||||
05:message/user:after compact
|
||||
00:compaction:encrypted=true
|
||||
01:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
02:message/user:<AGENTS_MD>
|
||||
03:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
04:message/user:after compact
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
---
|
||||
source: core/tests/suite/compact_remote.rs
|
||||
expression: "format_labeled_requests_snapshot(\"Remote mid-turn compaction after an earlier summary compaction: the older summary remains in model-visible history and round-trips into the next compact request.\",\n&[(\"Second Turn Request (Before Mid-Turn Compaction)\", &requests[1]),\n(\"Remote Compaction Request\", &compact_request),])"
|
||||
assertion_line: 1876
|
||||
expression: "format_labeled_requests_snapshot(\"After a prior manual /compact produced an older remote compaction item, the next turn hits remote auto-compaction before the next sampling request. The compact request carries forward that earlier compaction item, and the next sampling request shows the latest compaction item with context reinjected before USER_TWO.\",\n&[(\"Remote Compaction Request\", &compact_request),\n(\"Second Turn Request (After Compaction)\", &second_turn_request),])"
|
||||
---
|
||||
Scenario: Remote mid-turn compaction after an earlier summary compaction: the older summary remains in model-visible history and round-trips into the next compact request.
|
||||
|
||||
## Second Turn Request (Before Mid-Turn Compaction)
|
||||
00:message/user:USER_ONE
|
||||
01:message/user:<COMPACTION_SUMMARY>\nREMOTE_OLDER_SUMMARY
|
||||
02:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
03:message/user:<AGENTS_MD>
|
||||
04:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
05:message/user:<COMPACTION_SUMMARY>\nREMOTE_LATEST_SUMMARY
|
||||
06:message/user:USER_TWO
|
||||
Scenario: After a prior manual /compact produced an older remote compaction item, the next turn hits remote auto-compaction before the next sampling request. The compact request carries forward that earlier compaction item, and the next sampling request shows the latest compaction item with context reinjected before USER_TWO.
|
||||
|
||||
## Remote Compaction Request
|
||||
00:message/user:USER_ONE
|
||||
01:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
02:message/user:<AGENTS_MD>
|
||||
03:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
04:message/user:<COMPACTION_SUMMARY>\nREMOTE_OLDER_SUMMARY
|
||||
01:compaction:encrypted=true
|
||||
|
||||
## Second Turn Request (After Compaction)
|
||||
00:message/user:USER_ONE
|
||||
01:compaction:encrypted=true
|
||||
02:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
03:message/user:<AGENTS_MD>
|
||||
04:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
05:message/user:USER_TWO
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
source: core/tests/suite/compact_remote.rs
|
||||
expression: "format_labeled_requests_snapshot(\"Remote mid-turn continuation compaction after tool output: compact request includes tool artifacts and follow-up request includes the summary.\",\n&[(\"Remote Compaction Request\", &compact_request),\n(\"Remote Post-Compaction History Layout\", &requests[1]),])"
|
||||
expression: "format_labeled_requests_snapshot(\"Remote mid-turn continuation compaction after tool output: compact request includes tool artifacts and the follow-up request includes the returned compaction item.\",\n&[(\"Remote Compaction Request\", &compact_request),\n(\"Remote Post-Compaction History Layout\", &requests[1]),])"
|
||||
---
|
||||
Scenario: Remote mid-turn continuation compaction after tool output: compact request includes tool artifacts and follow-up request includes the summary.
|
||||
Scenario: Remote mid-turn continuation compaction after tool output: compact request includes tool artifacts and the follow-up request includes the returned compaction item.
|
||||
|
||||
## Remote Compaction Request
|
||||
00:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
@@ -13,8 +13,8 @@ Scenario: Remote mid-turn continuation compaction after tool output: compact req
|
||||
05:function_call_output:unsupported call: test_tool
|
||||
|
||||
## Remote Post-Compaction History Layout
|
||||
00:message/user:USER_ONE
|
||||
01:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
02:message/user:<AGENTS_MD>
|
||||
03:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
04:message/user:<COMPACTION_SUMMARY>\nREMOTE_MID_TURN_SUMMARY
|
||||
00:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
01:message/user:<AGENTS_MD>
|
||||
02:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
03:message/user:USER_ONE
|
||||
04:compaction:encrypted=true
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
source: core/tests/suite/compact_remote.rs
|
||||
expression: "format_labeled_requests_snapshot(\"Remote mid-turn compaction where compact output has only summary user content: continuation layout reinjects canonical context before that summary.\",\n&[(\"Remote Compaction Request\", &compact_request),\n(\"Remote Post-Compaction History Layout\", &requests[1]),])"
|
||||
expression: "format_labeled_requests_snapshot(\"Remote mid-turn compaction where compact output has only a compaction item: continuation layout reinjects context before that compaction item.\",\n&[(\"Remote Compaction Request\", &compact_request),\n(\"Remote Post-Compaction History Layout\", &requests[1]),])"
|
||||
---
|
||||
Scenario: Remote mid-turn compaction where compact output has only summary user content: continuation layout reinjects canonical context before that summary.
|
||||
Scenario: Remote mid-turn compaction where compact output has only a compaction item: continuation layout reinjects context before that compaction item.
|
||||
|
||||
## Remote Compaction Request
|
||||
00:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
@@ -16,4 +16,4 @@ Scenario: Remote mid-turn compaction where compact output has only summary user
|
||||
00:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
01:message/user:<AGENTS_MD>
|
||||
02:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
03:message/user:<COMPACTION_SUMMARY>\nREMOTE_SUMMARY_ONLY
|
||||
03:compaction:encrypted=true
|
||||
|
||||
@@ -12,13 +12,12 @@ Scenario: Remote pre-turn auto-compaction with a context override emits the cont
|
||||
04:message/assistant:REMOTE_FIRST_REPLY
|
||||
05:message/user:USER_TWO
|
||||
06:message/assistant:REMOTE_SECOND_REPLY
|
||||
07:message/user:<ENVIRONMENT_CONTEXT:cwd=PRETURN_CONTEXT_DIFF_CWD>
|
||||
|
||||
## Remote Post-Compaction History Layout
|
||||
00:message/user:USER_ONE
|
||||
01:message/user:USER_TWO
|
||||
02:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
03:message/user:<AGENTS_MD>
|
||||
04:message/user:<ENVIRONMENT_CONTEXT:cwd=PRETURN_CONTEXT_DIFF_CWD>
|
||||
05:message/user:<COMPACTION_SUMMARY>\nREMOTE_PRE_TURN_SUMMARY
|
||||
02:compaction:encrypted=true
|
||||
03:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
04:message/user:<AGENTS_MD>
|
||||
05:message/user:<ENVIRONMENT_CONTEXT:cwd=PRETURN_CONTEXT_DIFF_CWD>
|
||||
06:message/user:USER_THREE
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: core/tests/suite/compact_remote.rs
|
||||
expression: "format_labeled_requests_snapshot(\"Remote pre-turn compaction during model switch currently excludes incoming user input, strips incoming <model_switch> from the compact request payload, and restores it in the post-compaction follow-up request.\",\n&[(\"Initial Request (Previous Model)\", &requests[0]),\n(\"Remote Compaction Request\", &compact_request),\n(\"Remote Post-Compaction History Layout\", &requests[1]),])"
|
||||
expression: "format_labeled_requests_snapshot(\"Remote pre-turn compaction during model switch currently excludes incoming user input, strips incoming <model_switch> from the compact request payload, and restores it in the post-compaction follow-up request.\",\n&[(\"Initial Request (Previous Model)\", &initial_turn_request),\n(\"Remote Compaction Request\", &compact_request),\n(\"Remote Post-Compaction History Layout\", &post_compact_turn_request),])"
|
||||
---
|
||||
Scenario: Remote pre-turn compaction during model switch currently excludes incoming user input, strips incoming <model_switch> from the compact request payload, and restores it in the post-compaction follow-up request.
|
||||
|
||||
@@ -19,10 +19,10 @@ Scenario: Remote pre-turn compaction during model switch currently excludes inco
|
||||
|
||||
## Remote Post-Compaction History Layout
|
||||
00:message/user:BEFORE_SWITCH_USER
|
||||
01:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
02:message/developer:<personality_spec> The user has requested a new communication st...
|
||||
03:message/user:<AGENTS_MD>
|
||||
04:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
05:message/user:<COMPACTION_SUMMARY>\nREMOTE_SWITCH_SUMMARY
|
||||
06:message/developer:<model_switch>\nThe user was previously using a different model....
|
||||
01:compaction:encrypted=true
|
||||
02:message/developer:<model_switch>\nThe user was previously using a different model....
|
||||
03:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
04:message/developer:<personality_spec> The user has requested a new communication st...
|
||||
05:message/user:<AGENTS_MD>
|
||||
06:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
07:message/user:AFTER_SWITCH_USER
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
---
|
||||
source: core/tests/suite/model_visible_layout.rs
|
||||
assertion_line: 435
|
||||
expression: "format_labeled_requests_snapshot(\"First post-resume turn where pre-turn override sets model to rollout model; no model-switch update should appear.\",\n&[(\"Last Request Before Resume\", &initial_request),\n(\"First Request After Resume + Override\", &resumed_request),])"
|
||||
---
|
||||
Scenario: First post-resume turn where pre-turn override sets model to rollout model; no model-switch update should appear.
|
||||
@@ -16,7 +17,5 @@ Scenario: First post-resume turn where pre-turn override sets model to rollout m
|
||||
02:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
03:message/user:seed resume history
|
||||
04:message/assistant:recorded before resume
|
||||
05:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
06:message/user:<AGENTS_MD>
|
||||
07:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
08:message/user:first resumed turn after model override
|
||||
05:message/user:<ENVIRONMENT_CONTEXT:cwd=PRETURN_CONTEXT_DIFF_CWD>
|
||||
06:message/user:first resumed turn after model override
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
---
|
||||
source: core/tests/suite/model_visible_layout.rs
|
||||
assertion_line: 337
|
||||
expression: "format_labeled_requests_snapshot(\"First post-resume turn where resumed config model differs from rollout and personality changes.\",\n&[(\"Last Request Before Resume\", &initial_request),\n(\"First Request After Resume\", &resumed_request),])"
|
||||
---
|
||||
Scenario: First post-resume turn where resumed config model differs from rollout and personality changes.
|
||||
@@ -16,11 +17,7 @@ Scenario: First post-resume turn where resumed config model differs from rollout
|
||||
02:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
03:message/user:seed resume history
|
||||
04:message/assistant:recorded before resume
|
||||
05:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
06:message/developer:<personality_spec> The user has requested a new communication style. Future messages should adhe...
|
||||
07:message/user:<AGENTS_MD>
|
||||
08:message/user:<ENVIRONMENT_CONTEXT:cwd=<CWD>>
|
||||
09:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
10:message/developer:<model_switch>\nThe user was previously using a different model. Please continue the conversatio...
|
||||
11:message/developer:<personality_spec> The user has requested a new communication style. Future messages should adhe...
|
||||
12:message/user:resume and change personality
|
||||
05:message/developer:<model_switch>\nThe user was previously using a different model. Please continue the conversatio...
|
||||
06:message/user:<ENVIRONMENT_CONTEXT:cwd=PRETURN_CONTEXT_DIFF_CWD>
|
||||
07:message/developer:<PERMISSIONS_INSTRUCTIONS>
|
||||
08:message/user:resume and change personality
|
||||
|
||||
Reference in New Issue
Block a user