mirror of
https://github.com/openai/codex.git
synced 2026-10-22 17:58:46 +00:00
[codex-analytics] add queued submission metadata
This commit is contained in:
@@ -30,6 +30,7 @@ use crate::facts::SubAgentThreadStartedInput;
|
||||
use crate::facts::TrackEventsContext;
|
||||
use crate::facts::TurnResolvedConfigFact;
|
||||
use crate::facts::TurnStatus;
|
||||
use crate::facts::TurnSubmissionType;
|
||||
use crate::reducer::AnalyticsReducer;
|
||||
use crate::reducer::normalize_path_for_skill_id;
|
||||
use crate::reducer::skill_id_for_local_skill;
|
||||
@@ -240,7 +241,7 @@ fn sample_turn_resolved_config(turn_id: &str) -> TurnResolvedConfigFact {
|
||||
turn_id: turn_id.to_string(),
|
||||
thread_id: "thread-2".to_string(),
|
||||
num_input_images: 1,
|
||||
submission_type: None,
|
||||
submission_type: Some(TurnSubmissionType::Default),
|
||||
model: "gpt-5".to_string(),
|
||||
model_provider: "openai".to_string(),
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
@@ -1062,7 +1063,7 @@ fn turn_event_serializes_expected_shape() {
|
||||
thread_id: "thread-2".to_string(),
|
||||
turn_id: "turn-2".to_string(),
|
||||
product_client_id: "codex-tui".to_string(),
|
||||
submission_type: None,
|
||||
submission_type: Some(TurnSubmissionType::Default),
|
||||
model: Some("gpt-5".to_string()),
|
||||
model_provider: "openai".to_string(),
|
||||
sandbox_policy: Some("read_only"),
|
||||
@@ -1108,7 +1109,7 @@ fn turn_event_serializes_expected_shape() {
|
||||
"thread_id": "thread-2",
|
||||
"turn_id": "turn-2",
|
||||
"product_client_id": "codex-tui",
|
||||
"submission_type": null,
|
||||
"submission_type": "default",
|
||||
"model": "gpt-5",
|
||||
"model_provider": "openai",
|
||||
"sandbox_policy": "read_only",
|
||||
@@ -1196,6 +1197,89 @@ async fn turn_lifecycle_emits_turn_event() {
|
||||
assert_eq!(payload["event_params"]["total_tokens"], json!(321));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn queued_submission_type_emits_queued_turn_event() {
|
||||
let mut reducer = AnalyticsReducer::default();
|
||||
let mut out = Vec::new();
|
||||
|
||||
reducer
|
||||
.ingest(
|
||||
AnalyticsFact::Initialize {
|
||||
connection_id: 7,
|
||||
params: InitializeParams {
|
||||
client_info: ClientInfo {
|
||||
name: "codex-tui".to_string(),
|
||||
title: None,
|
||||
version: "1.0.0".to_string(),
|
||||
},
|
||||
capabilities: None,
|
||||
},
|
||||
product_client_id: "codex-tui".to_string(),
|
||||
runtime: CodexRuntimeMetadata {
|
||||
codex_rs_version: "0.1.0".to_string(),
|
||||
runtime_os: "macos".to_string(),
|
||||
runtime_os_version: "15.3.1".to_string(),
|
||||
runtime_arch: "aarch64".to_string(),
|
||||
},
|
||||
rpc_transport: AppServerRpcTransport::Stdio,
|
||||
},
|
||||
&mut out,
|
||||
)
|
||||
.await;
|
||||
reducer
|
||||
.ingest(
|
||||
AnalyticsFact::Request {
|
||||
connection_id: 7,
|
||||
request_id: RequestId::Integer(3),
|
||||
request: Box::new(sample_turn_start_request("thread-2", /*request_id*/ 3)),
|
||||
},
|
||||
&mut out,
|
||||
)
|
||||
.await;
|
||||
reducer
|
||||
.ingest(
|
||||
AnalyticsFact::Response {
|
||||
connection_id: 7,
|
||||
response: Box::new(sample_turn_start_response("turn-2", /*request_id*/ 3)),
|
||||
},
|
||||
&mut out,
|
||||
)
|
||||
.await;
|
||||
let mut resolved_config = sample_turn_resolved_config("turn-2");
|
||||
resolved_config.submission_type = Some(TurnSubmissionType::Queued);
|
||||
reducer
|
||||
.ingest(
|
||||
AnalyticsFact::Custom(CustomAnalyticsFact::TurnResolvedConfig(Box::new(
|
||||
resolved_config,
|
||||
))),
|
||||
&mut out,
|
||||
)
|
||||
.await;
|
||||
reducer
|
||||
.ingest(
|
||||
AnalyticsFact::Notification(Box::new(sample_turn_started_notification(
|
||||
"thread-2", "turn-2",
|
||||
))),
|
||||
&mut out,
|
||||
)
|
||||
.await;
|
||||
reducer
|
||||
.ingest(
|
||||
AnalyticsFact::Notification(Box::new(sample_turn_completed_notification(
|
||||
"thread-2",
|
||||
"turn-2",
|
||||
AppServerTurnStatus::Completed,
|
||||
/*codex_error_info*/ None,
|
||||
))),
|
||||
&mut out,
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_eq!(out.len(), 1);
|
||||
let payload = serde_json::to_value(&out[0]).expect("serialize turn event");
|
||||
assert_eq!(payload["event_params"]["submission_type"], json!("queued"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_does_not_emit_without_required_prerequisites() {
|
||||
let mut reducer = AnalyticsReducer::default();
|
||||
|
||||
@@ -2510,6 +2510,13 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"SubmissionType": {
|
||||
"enum": [
|
||||
"prompt",
|
||||
"prompt_queued"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"TextElement": {
|
||||
"properties": {
|
||||
"byteRange": {
|
||||
@@ -3278,6 +3285,17 @@
|
||||
],
|
||||
"description": "Override the service tier for this turn and subsequent turns."
|
||||
},
|
||||
"submissionType": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionType"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Metadata describing how the prompt was submitted."
|
||||
},
|
||||
"summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
@@ -12201,6 +12201,13 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"SubmissionType": {
|
||||
"enum": [
|
||||
"prompt",
|
||||
"prompt_queued"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"TerminalInteractionNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
@@ -14762,6 +14769,17 @@
|
||||
],
|
||||
"description": "Override the service tier for this turn and subsequent turns."
|
||||
},
|
||||
"submissionType": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/SubmissionType"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Metadata describing how the prompt was submitted."
|
||||
},
|
||||
"summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
@@ -10056,6 +10056,13 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"SubmissionType": {
|
||||
"enum": [
|
||||
"prompt",
|
||||
"prompt_queued"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"TerminalInteractionNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
@@ -12617,6 +12624,17 @@
|
||||
],
|
||||
"description": "Override the service tier for this turn and subsequent turns."
|
||||
},
|
||||
"submissionType": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionType"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Metadata describing how the prompt was submitted."
|
||||
},
|
||||
"summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
@@ -354,6 +354,13 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"SubmissionType": {
|
||||
"enum": [
|
||||
"prompt",
|
||||
"prompt_queued"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"TextElement": {
|
||||
"properties": {
|
||||
"byteRange": {
|
||||
@@ -595,6 +602,17 @@
|
||||
],
|
||||
"description": "Override the service tier for this turn and subsequent turns."
|
||||
},
|
||||
"submissionType": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SubmissionType"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Metadata describing how the prompt was submitted."
|
||||
},
|
||||
"summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type SubmissionType = "prompt" | "prompt_queued";
|
||||
@@ -65,6 +65,7 @@ export type { ServiceTier } from "./ServiceTier";
|
||||
export type { SessionSource } from "./SessionSource";
|
||||
export type { Settings } from "./Settings";
|
||||
export type { SubAgentSource } from "./SubAgentSource";
|
||||
export type { SubmissionType } from "./SubmissionType";
|
||||
export type { ThreadId } from "./ThreadId";
|
||||
export type { Tool } from "./Tool";
|
||||
export type { Verbosity } from "./Verbosity";
|
||||
|
||||
@@ -6,6 +6,7 @@ import type { Personality } from "../Personality";
|
||||
import type { ReasoningEffort } from "../ReasoningEffort";
|
||||
import type { ReasoningSummary } from "../ReasoningSummary";
|
||||
import type { ServiceTier } from "../ServiceTier";
|
||||
import type { SubmissionType } from "../SubmissionType";
|
||||
import type { JsonValue } from "../serde_json/JsonValue";
|
||||
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
|
||||
import type { AskForApproval } from "./AskForApproval";
|
||||
@@ -45,6 +46,9 @@ personality?: Personality | null, /**
|
||||
* this turn.
|
||||
*/
|
||||
outputSchema?: JsonValue | null, /**
|
||||
* Metadata describing how the prompt was submitted.
|
||||
*/
|
||||
submissionType?: SubmissionType | null, /**
|
||||
* EXPERIMENTAL - Set a pre-set collaboration mode.
|
||||
* Takes precedence over model, reasoning_effort, and developer instructions if set.
|
||||
*
|
||||
|
||||
@@ -80,6 +80,7 @@ use codex_protocol::protocol::SkillMetadata as CoreSkillMetadata;
|
||||
use codex_protocol::protocol::SkillScope as CoreSkillScope;
|
||||
use codex_protocol::protocol::SkillToolDependency as CoreSkillToolDependency;
|
||||
use codex_protocol::protocol::SubAgentSource as CoreSubAgentSource;
|
||||
use codex_protocol::protocol::SubmissionType;
|
||||
use codex_protocol::protocol::TokenUsage as CoreTokenUsage;
|
||||
use codex_protocol::protocol::TokenUsageInfo as CoreTokenUsageInfo;
|
||||
use codex_protocol::request_permissions::PermissionGrantScope as CorePermissionGrantScope;
|
||||
@@ -4058,6 +4059,11 @@ pub struct TurnStartParams {
|
||||
#[ts(optional = nullable)]
|
||||
pub output_schema: Option<JsonValue>,
|
||||
|
||||
/// Metadata describing how the prompt was submitted.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub submission_type: Option<SubmissionType>,
|
||||
|
||||
/// EXPERIMENTAL - Set a pre-set collaboration mode.
|
||||
/// Takes precedence over model, reasoning_effort, and developer instructions if set.
|
||||
///
|
||||
@@ -8417,6 +8423,7 @@ mod tests {
|
||||
service_tier: None,
|
||||
effort: None,
|
||||
summary: None,
|
||||
submission_type: None,
|
||||
output_schema: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
|
||||
@@ -6647,9 +6647,10 @@ impl CodexMessageProcessor {
|
||||
.submit_core_op(
|
||||
&request_id,
|
||||
thread.as_ref(),
|
||||
Op::UserInput {
|
||||
Op::UserInputWithMetadata {
|
||||
items: mapped_items,
|
||||
final_output_json_schema: params.output_schema,
|
||||
submission_type: params.submission_type,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -614,6 +614,7 @@ async fn turn_start_jsonrpc_span_parents_core_turn_spans() -> Result<()> {
|
||||
effort: None,
|
||||
summary: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
output_schema: None,
|
||||
collaboration_mode: None,
|
||||
},
|
||||
|
||||
@@ -155,6 +155,41 @@ pub(crate) async fn wait_for_analytics_event(
|
||||
.await?
|
||||
}
|
||||
|
||||
pub(crate) async fn wait_for_analytics_turn_event(
|
||||
server: &MockServer,
|
||||
read_timeout: Duration,
|
||||
turn_id: &str,
|
||||
) -> Result<Value> {
|
||||
timeout(read_timeout, async {
|
||||
loop {
|
||||
let Some(requests) = server.received_requests().await else {
|
||||
tokio::time::sleep(Duration::from_millis(25)).await;
|
||||
continue;
|
||||
};
|
||||
for request in &requests {
|
||||
if request.method != "POST"
|
||||
|| request.url.path() != "/codex/analytics-events/events"
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let payload: Value = serde_json::from_slice(&request.body)
|
||||
.map_err(|err| anyhow::anyhow!("invalid analytics payload: {err}"))?;
|
||||
let Some(events) = payload["events"].as_array() else {
|
||||
continue;
|
||||
};
|
||||
if let Some(event) = events.iter().find(|event| {
|
||||
event["event_type"] == "codex_turn_event"
|
||||
&& event["event_params"]["turn_id"] == turn_id
|
||||
}) {
|
||||
return Ok::<Value, anyhow::Error>(event.clone());
|
||||
}
|
||||
}
|
||||
tokio::time::sleep(Duration::from_millis(25)).await;
|
||||
}
|
||||
})
|
||||
.await?
|
||||
}
|
||||
|
||||
pub(crate) fn thread_initialized_event(payload: &Value) -> Result<&Value> {
|
||||
let events = payload["events"]
|
||||
.as_array()
|
||||
|
||||
@@ -55,6 +55,7 @@ use codex_protocol::config_types::Personality;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::Settings;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::protocol::SubmissionType;
|
||||
use codex_protocol::user_input::MAX_USER_INPUT_TEXT_CHARS;
|
||||
use core_test_support::responses;
|
||||
use core_test_support::skip_if_no_network;
|
||||
@@ -68,6 +69,7 @@ use tokio::time::timeout;
|
||||
|
||||
use super::analytics::enable_analytics_capture;
|
||||
use super::analytics::wait_for_analytics_event;
|
||||
use super::analytics::wait_for_analytics_turn_event;
|
||||
|
||||
#[cfg(windows)]
|
||||
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(25);
|
||||
@@ -401,7 +403,9 @@ async fn turn_start_tracks_turn_event_analytics() -> Result<()> {
|
||||
assert_eq!(event["event_params"]["model"], "mock-model");
|
||||
assert_eq!(event["event_params"]["model_provider"], "mock_provider");
|
||||
assert_eq!(event["event_params"]["sandbox_policy"], "read_only");
|
||||
assert_eq!(event["event_params"]["submission_type"], "default");
|
||||
assert_eq!(event["event_params"]["num_input_images"], 1);
|
||||
assert_eq!(event["event_params"]["is_first_turn"], true);
|
||||
assert_eq!(event["event_params"]["status"], "completed");
|
||||
assert!(event["event_params"]["started_at"].as_u64().is_some());
|
||||
assert!(event["event_params"]["completed_at"].as_u64().is_some());
|
||||
@@ -415,6 +419,106 @@ async fn turn_start_tracks_turn_event_analytics() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_tracks_second_turn_as_not_first_and_queued_submission_analytics() -> Result<()>
|
||||
{
|
||||
let responses = vec![
|
||||
create_final_assistant_message_sse_response("Done 1")?,
|
||||
create_final_assistant_message_sse_response("Done 2")?,
|
||||
];
|
||||
let server = create_mock_responses_server_sequence_unchecked(responses).await;
|
||||
|
||||
let codex_home = TempDir::new()?;
|
||||
write_mock_responses_config_toml_with_chatgpt_base_url(
|
||||
codex_home.path(),
|
||||
&server.uri(),
|
||||
&server.uri(),
|
||||
)?;
|
||||
enable_analytics_capture(&server, codex_home.path()).await?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let thread_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(thread_req)),
|
||||
)
|
||||
.await??;
|
||||
let ThreadStartResponse { thread, .. } = to_response::<ThreadStartResponse>(thread_resp)?;
|
||||
|
||||
let first_turn_req = mcp
|
||||
.send_turn_start_request(TurnStartParams {
|
||||
thread_id: thread.id.clone(),
|
||||
input: vec![V2UserInput::Text {
|
||||
text: "first turn".to_string(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let first_turn_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(first_turn_req)),
|
||||
)
|
||||
.await??;
|
||||
let TurnStartResponse { turn: first_turn } = to_response::<TurnStartResponse>(first_turn_resp)?;
|
||||
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_notification_message("turn/completed"),
|
||||
)
|
||||
.await??;
|
||||
|
||||
let first_turn_event =
|
||||
wait_for_analytics_turn_event(&server, DEFAULT_READ_TIMEOUT, &first_turn.id).await?;
|
||||
assert_eq!(
|
||||
first_turn_event["event_params"]["submission_type"],
|
||||
"default"
|
||||
);
|
||||
assert_eq!(first_turn_event["event_params"]["is_first_turn"], true);
|
||||
|
||||
let second_turn_req = mcp
|
||||
.send_turn_start_request(TurnStartParams {
|
||||
thread_id: thread.id,
|
||||
input: vec![V2UserInput::Text {
|
||||
text: "second turn".to_string(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
submission_type: Some(SubmissionType::PromptQueued),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let second_turn_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(second_turn_req)),
|
||||
)
|
||||
.await??;
|
||||
let TurnStartResponse { turn: second_turn } =
|
||||
to_response::<TurnStartResponse>(second_turn_resp)?;
|
||||
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_notification_message("turn/completed"),
|
||||
)
|
||||
.await??;
|
||||
|
||||
let second_turn_event =
|
||||
wait_for_analytics_turn_event(&server, DEFAULT_READ_TIMEOUT, &second_turn.id).await?;
|
||||
assert_eq!(
|
||||
second_turn_event["event_params"]["submission_type"],
|
||||
"queued"
|
||||
);
|
||||
assert_eq!(second_turn_event["event_params"]["is_first_turn"], false);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_tracks_failed_turn_event_analytics() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence(vec![String::new()]).await;
|
||||
@@ -1636,6 +1740,7 @@ async fn turn_start_updates_sandbox_and_cwd_between_turns_v2() -> Result<()> {
|
||||
summary: Some(ReasoningSummary::Auto),
|
||||
service_tier: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
output_schema: None,
|
||||
collaboration_mode: None,
|
||||
})
|
||||
@@ -1669,6 +1774,7 @@ async fn turn_start_updates_sandbox_and_cwd_between_turns_v2() -> Result<()> {
|
||||
summary: Some(ReasoningSummary::Auto),
|
||||
service_tier: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
output_schema: None,
|
||||
collaboration_mode: None,
|
||||
})
|
||||
|
||||
@@ -52,6 +52,7 @@ use codex_analytics::AppInvocation;
|
||||
use codex_analytics::InvocationType;
|
||||
use codex_analytics::SubAgentThreadStartedInput;
|
||||
use codex_analytics::TurnResolvedConfigFact;
|
||||
use codex_analytics::TurnSubmissionType;
|
||||
use codex_analytics::build_track_events_context;
|
||||
use codex_app_server_protocol::McpServerElicitationRequest;
|
||||
use codex_app_server_protocol::McpServerElicitationRequestParams;
|
||||
@@ -118,6 +119,7 @@ use codex_protocol::protocol::ReviewRequest;
|
||||
use codex_protocol::protocol::RolloutItem;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::SubAgentSource;
|
||||
use codex_protocol::protocol::SubmissionType;
|
||||
use codex_protocol::protocol::TurnAbortReason;
|
||||
use codex_protocol::protocol::TurnContextItem;
|
||||
use codex_protocol::protocol::TurnContextNetworkItem;
|
||||
@@ -894,6 +896,7 @@ pub(crate) struct TurnContext {
|
||||
pub(crate) current_date: Option<String>,
|
||||
pub(crate) timezone: Option<String>,
|
||||
pub(crate) app_server_client_name: Option<String>,
|
||||
pub(crate) submission_type: Option<SubmissionType>,
|
||||
pub(crate) developer_instructions: Option<String>,
|
||||
pub(crate) compact_prompt: Option<String>,
|
||||
pub(crate) user_instructions: Option<String>,
|
||||
@@ -1012,6 +1015,7 @@ impl TurnContext {
|
||||
current_date: self.current_date.clone(),
|
||||
timezone: self.timezone.clone(),
|
||||
app_server_client_name: self.app_server_client_name.clone(),
|
||||
submission_type: self.submission_type,
|
||||
developer_instructions: self.developer_instructions.clone(),
|
||||
compact_prompt: self.compact_prompt.clone(),
|
||||
user_instructions: self.user_instructions.clone(),
|
||||
@@ -1097,6 +1101,13 @@ impl TurnContext {
|
||||
}
|
||||
}
|
||||
|
||||
fn turn_submission_type(submission_type: SubmissionType) -> TurnSubmissionType {
|
||||
match submission_type {
|
||||
SubmissionType::Prompt => TurnSubmissionType::Default,
|
||||
SubmissionType::PromptQueued => TurnSubmissionType::Queued,
|
||||
}
|
||||
}
|
||||
|
||||
fn local_time_context() -> (String, String) {
|
||||
match iana_time_zone::get_timezone() {
|
||||
Ok(timezone) => (Local::now().format("%Y-%m-%d").to_string(), timezone),
|
||||
@@ -1270,6 +1281,7 @@ pub(crate) struct SessionSettingsUpdate {
|
||||
pub(crate) personality: Option<Personality>,
|
||||
pub(crate) app_server_client_name: Option<String>,
|
||||
pub(crate) app_server_client_version: Option<String>,
|
||||
pub(crate) submission_type: Option<SubmissionType>,
|
||||
}
|
||||
|
||||
pub(crate) struct AppServerClientMetadata {
|
||||
@@ -1438,6 +1450,7 @@ impl Session {
|
||||
network: Option<NetworkProxy>,
|
||||
environment: Option<Arc<Environment>>,
|
||||
sub_id: String,
|
||||
submission_type: Option<SubmissionType>,
|
||||
js_repl: Arc<JsReplHandle>,
|
||||
skills_outcome: Arc<SkillLoadOutcome>,
|
||||
) -> TurnContext {
|
||||
@@ -1502,6 +1515,7 @@ impl Session {
|
||||
current_date: Some(current_date),
|
||||
timezone: Some(timezone),
|
||||
app_server_client_name: session_configuration.app_server_client_name.clone(),
|
||||
submission_type,
|
||||
developer_instructions: session_configuration.developer_instructions.clone(),
|
||||
compact_prompt: session_configuration.compact_prompt.clone(),
|
||||
user_instructions: session_configuration.user_instructions.clone(),
|
||||
@@ -2512,6 +2526,7 @@ impl Session {
|
||||
sub_id,
|
||||
session_configuration,
|
||||
updates.final_output_json_schema,
|
||||
updates.submission_type,
|
||||
sandbox_policy_changed,
|
||||
)
|
||||
.await)
|
||||
@@ -2522,6 +2537,7 @@ impl Session {
|
||||
sub_id: String,
|
||||
session_configuration: SessionConfiguration,
|
||||
final_output_json_schema: Option<Option<Value>>,
|
||||
submission_type: Option<SubmissionType>,
|
||||
sandbox_policy_changed: bool,
|
||||
) -> Arc<TurnContext> {
|
||||
let per_turn_config = Self::build_per_turn_config(&session_configuration);
|
||||
@@ -2587,6 +2603,7 @@ impl Session {
|
||||
.map(StartedNetworkProxy::proxy),
|
||||
self.services.environment.clone(),
|
||||
sub_id,
|
||||
submission_type,
|
||||
Arc::clone(&self.js_repl),
|
||||
skills_outcome,
|
||||
);
|
||||
@@ -2699,6 +2716,7 @@ impl Session {
|
||||
sub_id,
|
||||
session_configuration,
|
||||
/*final_output_json_schema*/ None,
|
||||
/*submission_type*/ None,
|
||||
/*sandbox_policy_changed*/ false,
|
||||
)
|
||||
.await
|
||||
@@ -4633,7 +4651,7 @@ async fn submission_loop(sess: Arc<Session>, config: Arc<Config>, rx_sub: Receiv
|
||||
.await;
|
||||
false
|
||||
}
|
||||
Op::UserInput { .. } | Op::UserTurn { .. } => {
|
||||
Op::UserInput { .. } | Op::UserInputWithMetadata { .. } | Op::UserTurn { .. } => {
|
||||
handlers::user_input_or_turn(&sess, sub.id.clone(), sub.op).await;
|
||||
false
|
||||
}
|
||||
@@ -4891,6 +4909,7 @@ mod handlers {
|
||||
items,
|
||||
collaboration_mode,
|
||||
personality,
|
||||
submission_type,
|
||||
} => {
|
||||
let collaboration_mode = collaboration_mode.or_else(|| {
|
||||
Some(CollaborationMode {
|
||||
@@ -4917,9 +4936,22 @@ mod handlers {
|
||||
personality,
|
||||
app_server_client_name: None,
|
||||
app_server_client_version: None,
|
||||
submission_type,
|
||||
},
|
||||
)
|
||||
}
|
||||
Op::UserInputWithMetadata {
|
||||
items,
|
||||
final_output_json_schema,
|
||||
submission_type,
|
||||
} => (
|
||||
items,
|
||||
SessionSettingsUpdate {
|
||||
final_output_json_schema: Some(final_output_json_schema),
|
||||
submission_type,
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
Op::UserInput {
|
||||
items,
|
||||
final_output_json_schema,
|
||||
@@ -5733,6 +5765,7 @@ async fn spawn_review_thread(
|
||||
current_date: parent_turn_context.current_date.clone(),
|
||||
timezone: parent_turn_context.timezone.clone(),
|
||||
app_server_client_name: parent_turn_context.app_server_client_name.clone(),
|
||||
submission_type: None,
|
||||
developer_instructions: None,
|
||||
user_instructions: None,
|
||||
compact_prompt: parent_turn_context.compact_prompt.clone(),
|
||||
@@ -6367,7 +6400,12 @@ async fn track_turn_resolved_config_analytics(
|
||||
matches!(item, UserInput::Image { .. } | UserInput::LocalImage { .. })
|
||||
})
|
||||
.count(),
|
||||
submission_type: None,
|
||||
submission_type: Some(
|
||||
turn_context
|
||||
.submission_type
|
||||
.map(turn_submission_type)
|
||||
.unwrap_or(TurnSubmissionType::Default),
|
||||
),
|
||||
model: turn_context.model_info.slug.clone(),
|
||||
model_provider: turn_context.config.model_provider_id.clone(),
|
||||
sandbox_policy: turn_context.sandbox_policy.get().clone(),
|
||||
|
||||
@@ -2806,6 +2806,7 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) {
|
||||
/*network*/ None,
|
||||
Some(environment),
|
||||
"turn_id".to_string(),
|
||||
/*submission_type*/ None,
|
||||
Arc::clone(&js_repl),
|
||||
skills_outcome,
|
||||
);
|
||||
@@ -3174,6 +3175,7 @@ async fn user_turn_updates_approvals_reviewer() {
|
||||
final_output_json_schema: None,
|
||||
collaboration_mode: None,
|
||||
personality: config.personality,
|
||||
submission_type: None,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
@@ -3646,6 +3648,7 @@ pub(crate) async fn make_session_and_context_with_dynamic_tools_and_rx(
|
||||
/*network*/ None,
|
||||
Some(environment),
|
||||
"turn_id".to_string(),
|
||||
/*submission_type*/ None,
|
||||
Arc::clone(&js_repl),
|
||||
skills_outcome,
|
||||
));
|
||||
|
||||
@@ -523,6 +523,7 @@ async fn run_review_on_session(
|
||||
final_output_json_schema: Some(params.schema.clone()),
|
||||
collaboration_mode: None,
|
||||
personality: params.personality,
|
||||
submission_type: None,
|
||||
})
|
||||
.await
|
||||
}),
|
||||
|
||||
@@ -759,6 +759,7 @@ impl TestCodex {
|
||||
service_tier,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -368,6 +368,7 @@ async fn apply_patch_cli_move_without_content_change_has_no_turn_diff(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -978,6 +979,7 @@ async fn apply_patch_shell_command_heredoc_with_cd_emits_turn_diff() -> Result<(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1060,6 +1062,7 @@ async fn apply_patch_shell_command_failure_propagates_error_and_skips_diff() ->
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1212,6 +1215,7 @@ async fn apply_patch_emits_turn_diff_event_with_unified_diff(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1277,6 +1281,7 @@ async fn apply_patch_turn_diff_for_rename_with_content_change(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1350,6 +1355,7 @@ async fn apply_patch_aggregates_diff_across_multiple_tool_calls() -> Result<()>
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1423,6 +1429,7 @@ async fn apply_patch_aggregates_diff_preserves_success_after_failure() -> Result
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -597,6 +597,7 @@ async fn submit_turn(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -1668,6 +1668,7 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re
|
||||
collaboration_mode: Some(collaboration_mode),
|
||||
final_output_json_schema: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1782,6 +1783,7 @@ async fn user_turn_explicit_reasoning_summary_overrides_model_catalog_default()
|
||||
collaboration_mode: None,
|
||||
final_output_json_schema: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -2368,6 +2368,7 @@ text(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -191,6 +191,7 @@ async fn collaboration_instructions_added_on_user_turn() -> Result<()> {
|
||||
collaboration_mode: Some(collaboration_mode),
|
||||
final_output_json_schema: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -307,6 +308,7 @@ async fn user_turn_overrides_collaboration_instructions_after_override() -> Resu
|
||||
collaboration_mode: Some(turn_mode),
|
||||
final_output_json_schema: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
|
||||
@@ -1668,6 +1668,7 @@ async fn auto_compact_runs_after_resume_when_token_usage_is_over_limit() {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -1759,6 +1760,7 @@ async fn pre_sampling_compact_runs_on_switch_to_smaller_context_model() {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await
|
||||
.expect("submit first user turn");
|
||||
@@ -1784,6 +1786,7 @@ async fn pre_sampling_compact_runs_on_switch_to_smaller_context_model() {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await
|
||||
.expect("submit second user turn");
|
||||
@@ -1895,6 +1898,7 @@ async fn pre_sampling_compact_runs_after_resume_and_switch_to_smaller_model() {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await
|
||||
.expect("submit pre-resume turn");
|
||||
@@ -1944,6 +1948,7 @@ async fn pre_sampling_compact_runs_after_resume_and_switch_to_smaller_model() {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await
|
||||
.expect("submit resumed user turn");
|
||||
@@ -3149,6 +3154,7 @@ async fn snapshot_request_shape_pre_turn_compaction_strips_incoming_model_switch
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await
|
||||
.expect("submit first user turn");
|
||||
@@ -3174,6 +3180,7 @@ async fn snapshot_request_shape_pre_turn_compaction_strips_incoming_model_switch
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await
|
||||
.expect("submit second user turn");
|
||||
|
||||
@@ -59,6 +59,7 @@ async fn submit_user_turn(
|
||||
service_tier: None,
|
||||
collaboration_mode,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
@@ -140,6 +141,7 @@ async fn execpolicy_blocks_shell_invocation() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -130,6 +130,7 @@ async fn copy_paste_local_image_persists_rollout_request_shape() -> anyhow::Resu
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -214,6 +215,7 @@ async fn drag_drop_image_persists_rollout_request_shape() -> anyhow::Result<()>
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -530,6 +530,7 @@ async fn plan_mode_emits_plan_item_from_proposed_plan_block() -> anyhow::Result<
|
||||
service_tier: None,
|
||||
collaboration_mode: Some(collaboration_mode),
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -607,6 +608,7 @@ async fn plan_mode_strips_plan_from_agent_messages() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: Some(collaboration_mode),
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -716,6 +718,7 @@ async fn plan_mode_streaming_citations_are_stripped_across_added_deltas_and_done
|
||||
service_tier: None,
|
||||
collaboration_mode: Some(collaboration_mode),
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -903,6 +906,7 @@ async fn plan_mode_streaming_proposed_plan_tag_split_across_added_and_delta_is_p
|
||||
service_tier: None,
|
||||
collaboration_mode: Some(collaboration_mode),
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1017,6 +1021,7 @@ async fn plan_mode_handles_missing_plan_close_tag() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: Some(collaboration_mode),
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ async fn codex_returns_json_result(model: String) -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ async fn submit_skill_turn(test: &TestCodex, skill_path: PathBuf, prompt: &str)
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -134,6 +134,7 @@ async fn model_change_appends_model_instructions_developer_message() -> Result<(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -171,6 +172,7 @@ async fn model_change_appends_model_instructions_developer_message() -> Result<(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -231,6 +233,7 @@ async fn model_and_personality_change_only_appends_model_instructions() -> Resul
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -268,6 +271,7 @@ async fn model_and_personality_change_only_appends_model_instructions() -> Resul
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -410,6 +414,7 @@ async fn model_change_from_image_to_text_strips_prior_image_content() -> Result<
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -431,6 +436,7 @@ async fn model_change_from_image_to_text_strips_prior_image_content() -> Result<
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -539,6 +545,7 @@ async fn generated_image_is_replayed_for_image_capable_models() -> Result<()> {
|
||||
summary: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -560,6 +567,7 @@ async fn generated_image_is_replayed_for_image_capable_models() -> Result<()> {
|
||||
summary: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -671,6 +679,7 @@ async fn model_change_from_generated_image_to_text_preserves_prior_generated_ima
|
||||
summary: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -692,6 +701,7 @@ async fn model_change_from_generated_image_to_text_preserves_prior_generated_ima
|
||||
summary: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -805,6 +815,7 @@ async fn thread_rollback_after_generated_image_drops_entire_image_turn_history()
|
||||
summary: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -834,6 +845,7 @@ async fn thread_rollback_after_generated_image_drops_entire_image_turn_history()
|
||||
summary: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -989,6 +1001,7 @@ async fn model_switch_to_smaller_model_updates_token_context_window() -> Result<
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1048,6 +1061,7 @@ async fn model_switch_to_smaller_model_updates_token_context_window() -> Result<
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ async fn snapshot_model_visible_layout_turn_overrides() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |event| {
|
||||
@@ -153,6 +154,7 @@ async fn snapshot_model_visible_layout_turn_overrides() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: Some(Personality::Friendly),
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |event| {
|
||||
@@ -232,6 +234,7 @@ async fn snapshot_model_visible_layout_cwd_change_does_not_refresh_agents() -> R
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |event| {
|
||||
@@ -256,6 +259,7 @@ async fn snapshot_model_visible_layout_cwd_change_does_not_refresh_agents() -> R
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |event| {
|
||||
@@ -366,6 +370,7 @@ async fn snapshot_model_visible_layout_resume_with_personality_change() -> Resul
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: Some(Personality::Friendly),
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&resumed.codex, |event| {
|
||||
|
||||
@@ -105,6 +105,7 @@ async fn renews_cache_ttl_on_matching_models_etag() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -110,6 +110,7 @@ async fn refresh_models_on_models_etag_mismatch_and_avoid_duplicate_models_fetch
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ async fn user_turn_personality_none_does_not_add_update_message() -> anyhow::Res
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -162,6 +163,7 @@ async fn config_personality_some_sets_instructions_template() -> anyhow::Result<
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -220,6 +222,7 @@ async fn config_personality_none_sends_no_personality() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -284,6 +287,7 @@ async fn default_personality_is_pragmatic_without_config_toml() -> anyhow::Resul
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -336,6 +340,7 @@ async fn user_turn_personality_some_adds_update_message() -> anyhow::Result<()>
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -374,6 +379,7 @@ async fn user_turn_personality_some_adds_update_message() -> anyhow::Result<()>
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -441,6 +447,7 @@ async fn user_turn_personality_same_value_does_not_add_update_message() -> anyho
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -479,6 +486,7 @@ async fn user_turn_personality_same_value_does_not_add_update_message() -> anyho
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -559,6 +567,7 @@ async fn user_turn_personality_skips_if_feature_disabled() -> anyhow::Result<()>
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -597,6 +606,7 @@ async fn user_turn_personality_skips_if_feature_disabled() -> anyhow::Result<()>
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -714,6 +724,7 @@ async fn remote_model_friendly_personality_instructions_with_feature() -> anyhow
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: Some(Personality::Friendly),
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -833,6 +844,7 @@ async fn user_turn_personality_remote_model_template_includes_update_message() -
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -871,6 +883,7 @@ async fn user_turn_personality_remote_model_template_includes_update_message() -
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -712,6 +712,7 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res
|
||||
collaboration_mode: None,
|
||||
final_output_json_schema: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -825,6 +826,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a
|
||||
collaboration_mode: None,
|
||||
final_output_json_schema: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -846,6 +848,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a
|
||||
collaboration_mode: None,
|
||||
final_output_json_schema: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -951,6 +954,7 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu
|
||||
collaboration_mode: None,
|
||||
final_output_json_schema: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -972,6 +976,7 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu
|
||||
collaboration_mode: None,
|
||||
final_output_json_schema: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
|
||||
@@ -184,6 +184,7 @@ async fn remote_models_long_model_slug_is_sent_with_high_reasoning() -> Result<(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -247,6 +248,7 @@ async fn namespaced_model_slug_uses_catalog_metadata_without_fallback_warning()
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -407,6 +409,7 @@ async fn remote_models_remote_model_uses_unified_exec() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -630,6 +633,7 @@ async fn remote_models_apply_remote_base_instructions() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -202,6 +202,7 @@ async fn submit_turn(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
|
||||
@@ -153,6 +153,7 @@ async fn submit_turn(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
|
||||
@@ -153,6 +153,7 @@ async fn request_user_input_round_trip_for_mode(mode: ModeKind) -> anyhow::Resul
|
||||
},
|
||||
}),
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -264,6 +265,7 @@ where
|
||||
service_tier: None,
|
||||
collaboration_mode: Some(collaboration_mode),
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -138,6 +138,7 @@ async fn stdio_server_round_trip() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -309,6 +310,7 @@ async fn stdio_image_responses_round_trip() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -514,6 +516,7 @@ async fn stdio_image_responses_are_sanitized_for_text_only_model() -> anyhow::Re
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -630,6 +633,7 @@ async fn stdio_server_propagates_whitelisted_env_vars() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -793,6 +797,7 @@ async fn streamable_http_tool_call_round_trip() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1041,6 +1046,7 @@ async fn streamable_http_with_oauth_round_trip_impl() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ async fn openai_model_header_mismatch_emits_warning_event_and_warning_item() ->
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -152,6 +153,7 @@ async fn response_model_field_mismatch_emits_warning_when_header_matches_request
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -238,6 +240,7 @@ async fn openai_model_header_mismatch_only_emits_one_warning_per_turn() -> Resul
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -288,6 +291,7 @@ async fn openai_model_header_casing_only_mismatch_does_not_warn() -> Result<()>
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -172,6 +172,7 @@ async fn run_snapshot_command_with_options(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -263,6 +264,7 @@ async fn run_shell_command_snapshot_with_options(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -334,6 +336,7 @@ async fn run_tool_turn_on_harness(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -568,6 +571,7 @@ async fn shell_command_snapshot_still_intercepts_apply_patch() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ async fn submit_turn_with_policies(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
|
||||
@@ -82,6 +82,7 @@ async fn user_turn_includes_skill_instructions() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -404,6 +404,7 @@ async fn mcp_call_marks_thread_memory_mode_polluted_when_configured() -> Result<
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |event| {
|
||||
|
||||
@@ -93,6 +93,7 @@ async fn shell_tool_executes_command_and_streams_output() -> anyhow::Result<()>
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -164,6 +165,7 @@ async fn update_plan_tool_emits_plan_update_event() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -245,6 +247,7 @@ async fn update_plan_tool_rejects_malformed_payload() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -341,6 +344,7 @@ async fn apply_patch_tool_executes_and_emits_patch_events() -> anyhow::Result<()
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -445,6 +449,7 @@ async fn apply_patch_reports_parse_diagnostics() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ async fn run_turn(test: &TestCodex, prompt: &str) -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -367,6 +368,7 @@ async fn shell_tools_start_before_response_completed_when_stream_delayed() -> an
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -496,6 +496,7 @@ async fn mcp_image_output_preserves_image_and_no_text_summary() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -200,6 +200,7 @@ async fn unified_exec_intercepts_apply_patch_exec_command() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -334,6 +335,7 @@ async fn unified_exec_emits_exec_command_begin_event() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -417,6 +419,7 @@ async fn unified_exec_resolves_relative_workdir() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -503,6 +506,7 @@ async fn unified_exec_respects_workdir_override() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -601,6 +605,7 @@ async fn unified_exec_emits_exec_command_end_event() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -681,6 +686,7 @@ async fn unified_exec_emits_output_delta_for_exec_command() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -762,6 +768,7 @@ async fn unified_exec_full_lifecycle_with_background_end_event() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -897,6 +904,7 @@ async fn unified_exec_emits_terminal_interaction_for_write_stdin() -> Result<()>
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1039,6 +1047,7 @@ async fn unified_exec_terminal_interaction_captures_delayed_output() -> Result<(
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1204,6 +1213,7 @@ async fn unified_exec_emits_one_begin_and_one_end_event() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1317,6 +1327,7 @@ async fn exec_command_reports_chunk_and_exit_metadata() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1440,6 +1451,7 @@ async fn unified_exec_defaults_to_pipe() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1535,6 +1547,7 @@ async fn unified_exec_can_enable_tty() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1621,6 +1634,7 @@ async fn unified_exec_respects_early_exit_notifications() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1757,6 +1771,7 @@ async fn write_stdin_returns_exit_metadata_and_clears_session() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1930,6 +1945,7 @@ async fn unified_exec_emits_end_event_when_session_dies_via_stdin() -> Result<()
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -2012,6 +2028,7 @@ async fn unified_exec_keeps_long_running_session_after_turn_end() -> Result<()>
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -2105,6 +2122,7 @@ async fn unified_exec_interrupt_preserves_long_running_session() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -2214,6 +2232,7 @@ async fn unified_exec_reuses_session_via_stdin() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -2354,6 +2373,7 @@ PY
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
// This is a worst case scenario for the truncate logic.
|
||||
@@ -2473,6 +2493,7 @@ async fn unified_exec_timeout_and_followup_poll() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -2574,6 +2595,7 @@ PY
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -2675,6 +2697,7 @@ async fn unified_exec_runs_under_sandbox() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -2784,6 +2807,7 @@ async fn unified_exec_python_prompt_under_seatbelt() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -2884,6 +2908,7 @@ async fn unified_exec_runs_on_all_platforms() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -3024,6 +3049,7 @@ async fn unified_exec_prunes_exited_sessions_first() -> Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -185,6 +185,7 @@ async fn user_shell_command_does_not_replace_active_turn() -> anyhow::Result<()>
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -164,6 +164,7 @@ async fn user_turn_with_local_image_attaches_image() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -273,6 +274,7 @@ async fn view_image_tool_attaches_local_image() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -414,6 +416,7 @@ async fn view_image_tool_can_preserve_original_resolution_when_requested_on_gpt5
|
||||
summary: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -520,6 +523,7 @@ async fn view_image_tool_errors_clearly_for_unsupported_detail_values() -> anyho
|
||||
summary: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -612,6 +616,7 @@ async fn view_image_tool_treats_null_detail_as_omitted() -> anyhow::Result<()> {
|
||||
summary: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -712,6 +717,7 @@ async fn view_image_tool_resizes_when_model_lacks_original_detail_support() -> a
|
||||
summary: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -823,6 +829,7 @@ async fn view_image_tool_does_not_force_original_resolution_with_capability_feat
|
||||
summary: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -925,6 +932,7 @@ await codex.emitImage(out);
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1045,6 +1053,7 @@ console.log(out.type);
|
||||
summary: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1138,6 +1147,7 @@ async fn view_image_tool_errors_when_path_is_directory() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1214,6 +1224,7 @@ async fn view_image_tool_errors_for_non_image_files() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1295,6 +1306,7 @@ async fn view_image_tool_errors_when_file_missing() -> anyhow::Result<()> {
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1425,6 +1437,7 @@ async fn view_image_tool_returns_unsupported_message_for_text_only_model() -> an
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -1500,6 +1513,7 @@ async fn replaces_invalid_local_image_after_bad_request() -> anyhow::Result<()>
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@ async fn websocket_fallback_hides_first_websocket_retry_stream_error() -> Result
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -689,6 +689,7 @@ async fn run_exec_session(args: ExecRunArgs) -> anyhow::Result<()> {
|
||||
effort: default_effort,
|
||||
summary: None,
|
||||
personality: None,
|
||||
submission_type: None,
|
||||
output_schema,
|
||||
collaboration_mode: None,
|
||||
},
|
||||
|
||||
@@ -103,6 +103,13 @@ pub const REALTIME_CONVERSATION_OPEN_TAG: &str = "<realtime_conversation>";
|
||||
pub const REALTIME_CONVERSATION_CLOSE_TAG: &str = "</realtime_conversation>";
|
||||
pub const USER_MESSAGE_BEGIN: &str = "## My request for Codex:";
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum SubmissionType {
|
||||
Prompt,
|
||||
PromptQueued,
|
||||
}
|
||||
|
||||
/// Submission Queue Entry - requests from user
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
|
||||
pub struct Submission {
|
||||
@@ -246,6 +253,19 @@ pub enum Op {
|
||||
final_output_json_schema: Option<Value>,
|
||||
},
|
||||
|
||||
/// Same transport shape as [`Op::UserInput`], but preserves submission
|
||||
/// metadata for analytics.
|
||||
UserInputWithMetadata {
|
||||
/// User input items, see `InputItem`
|
||||
items: Vec<UserInput>,
|
||||
/// Optional JSON Schema used to constrain the final assistant message for this turn.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
final_output_json_schema: Option<Value>,
|
||||
/// Metadata describing how the prompt was submitted.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
submission_type: Option<SubmissionType>,
|
||||
},
|
||||
|
||||
/// Similar to [`Op::UserInput`], but contains additional context required
|
||||
/// for a turn of a [`crate::codex_thread::CodexThread`].
|
||||
UserTurn {
|
||||
@@ -301,6 +321,10 @@ pub enum Op {
|
||||
/// Optional personality override for this turn.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
personality: Option<Personality>,
|
||||
|
||||
/// Metadata describing how the prompt was submitted.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
submission_type: Option<SubmissionType>,
|
||||
},
|
||||
|
||||
/// Inter-agent communication that should be recorded as assistant history
|
||||
@@ -581,6 +605,7 @@ impl Op {
|
||||
Self::RealtimeConversationText(_) => "realtime_conversation_text",
|
||||
Self::RealtimeConversationClose => "realtime_conversation_close",
|
||||
Self::UserInput { .. } => "user_input",
|
||||
Self::UserInputWithMetadata { .. } => "user_input",
|
||||
Self::UserTurn { .. } => "user_turn",
|
||||
Self::InterAgentCommunication { .. } => "inter_agent_communication",
|
||||
Self::OverrideTurnContext { .. } => "override_turn_context",
|
||||
|
||||
@@ -2234,6 +2234,7 @@ impl App {
|
||||
final_output_json_schema,
|
||||
collaboration_mode,
|
||||
personality,
|
||||
submission_type,
|
||||
} => {
|
||||
let mut should_start_turn = true;
|
||||
if let Some(turn_id) = self.active_turn_id_for_thread(thread_id).await {
|
||||
@@ -2316,6 +2317,7 @@ impl App {
|
||||
*service_tier,
|
||||
collaboration_mode.clone(),
|
||||
*personality,
|
||||
*submission_type,
|
||||
final_output_json_schema.clone(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -17,6 +17,7 @@ use codex_protocol::protocol::Op;
|
||||
use codex_protocol::protocol::ReviewDecision;
|
||||
use codex_protocol::protocol::ReviewRequest;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use codex_protocol::protocol::SubmissionType;
|
||||
use codex_protocol::request_permissions::RequestPermissionsResponse;
|
||||
use codex_protocol::request_user_input::RequestUserInputResponse;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
@@ -51,6 +52,7 @@ pub(crate) enum AppCommandView<'a> {
|
||||
final_output_json_schema: &'a Option<Value>,
|
||||
collaboration_mode: &'a Option<CollaborationMode>,
|
||||
personality: &'a Option<Personality>,
|
||||
submission_type: &'a Option<SubmissionType>,
|
||||
},
|
||||
OverrideTurnContext {
|
||||
cwd: &'a Option<PathBuf>,
|
||||
@@ -152,6 +154,7 @@ impl AppCommand {
|
||||
final_output_json_schema: Option<Value>,
|
||||
collaboration_mode: Option<CollaborationMode>,
|
||||
personality: Option<Personality>,
|
||||
submission_type: Option<SubmissionType>,
|
||||
) -> Self {
|
||||
Self(Op::UserTurn {
|
||||
items,
|
||||
@@ -166,6 +169,7 @@ impl AppCommand {
|
||||
final_output_json_schema,
|
||||
collaboration_mode,
|
||||
personality,
|
||||
submission_type,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -311,6 +315,7 @@ impl AppCommand {
|
||||
final_output_json_schema,
|
||||
collaboration_mode,
|
||||
personality,
|
||||
submission_type,
|
||||
} => AppCommandView::UserTurn {
|
||||
items,
|
||||
cwd,
|
||||
@@ -324,6 +329,7 @@ impl AppCommand {
|
||||
final_output_json_schema,
|
||||
collaboration_mode,
|
||||
personality,
|
||||
submission_type,
|
||||
},
|
||||
Op::OverrideTurnContext {
|
||||
cwd,
|
||||
|
||||
@@ -82,6 +82,7 @@ use codex_protocol::protocol::ReviewRequest;
|
||||
use codex_protocol::protocol::ReviewTarget as CoreReviewTarget;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use codex_protocol::protocol::SessionNetworkProxyRuntime;
|
||||
use codex_protocol::protocol::SubmissionType;
|
||||
use color_eyre::eyre::ContextCompat;
|
||||
use color_eyre::eyre::Result;
|
||||
use color_eyre::eyre::WrapErr;
|
||||
@@ -425,6 +426,7 @@ impl AppServerSession {
|
||||
service_tier: Option<Option<codex_protocol::config_types::ServiceTier>>,
|
||||
collaboration_mode: Option<codex_protocol::config_types::CollaborationMode>,
|
||||
personality: Option<codex_protocol::config_types::Personality>,
|
||||
submission_type: Option<SubmissionType>,
|
||||
output_schema: Option<serde_json::Value>,
|
||||
) -> Result<TurnStartResponse> {
|
||||
let request_id = self.next_request_id();
|
||||
@@ -443,6 +445,7 @@ impl AppServerSession {
|
||||
effort,
|
||||
summary,
|
||||
personality,
|
||||
submission_type,
|
||||
output_schema,
|
||||
collaboration_mode,
|
||||
},
|
||||
|
||||
@@ -193,6 +193,7 @@ use codex_protocol::protocol::ReviewTarget;
|
||||
use codex_protocol::protocol::SkillMetadata as ProtocolSkillMetadata;
|
||||
#[cfg(test)]
|
||||
use codex_protocol::protocol::StreamErrorEvent;
|
||||
use codex_protocol::protocol::SubmissionType;
|
||||
use codex_protocol::protocol::TerminalInteractionEvent;
|
||||
use codex_protocol::protocol::TokenUsage;
|
||||
use codex_protocol::protocol::TokenUsageInfo;
|
||||
@@ -5567,6 +5568,14 @@ impl ChatWidget {
|
||||
}
|
||||
|
||||
fn submit_user_message(&mut self, user_message: UserMessage) {
|
||||
self.submit_user_message_with_type(user_message, /*submission_type*/ None);
|
||||
}
|
||||
|
||||
fn submit_user_message_with_type(
|
||||
&mut self,
|
||||
user_message: UserMessage,
|
||||
submission_type: Option<SubmissionType>,
|
||||
) {
|
||||
if !self.is_session_configured() {
|
||||
tracing::warn!("cannot submit user message before session is configured; queueing");
|
||||
self.queued_user_messages.push_front(user_message);
|
||||
@@ -5782,6 +5791,7 @@ impl ChatWidget {
|
||||
/*final_output_json_schema*/ None,
|
||||
collaboration_mode,
|
||||
personality,
|
||||
submission_type,
|
||||
);
|
||||
|
||||
if !self.submit_op(op) {
|
||||
@@ -7243,8 +7253,13 @@ impl ChatWidget {
|
||||
if self.bottom_pane.is_task_running() {
|
||||
return;
|
||||
}
|
||||
let submission_type = if self.rejected_steers_queue.is_empty() {
|
||||
Some(SubmissionType::PromptQueued)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(user_message) = self.pop_next_queued_user_message() {
|
||||
self.submit_user_message(user_message);
|
||||
self.submit_user_message_with_type(user_message, submission_type);
|
||||
}
|
||||
// Update the list to reflect the remaining queued messages (if any).
|
||||
self.refresh_pending_input_preview();
|
||||
|
||||
@@ -642,6 +642,29 @@ async fn interrupted_turn_restore_keeps_active_mode_for_resubmission() {
|
||||
assert_eq!(chat.active_collaboration_mode_kind(), expected_mode);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn queued_user_message_marks_prompt_queued_submission_type() {
|
||||
let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5")).await;
|
||||
chat.thread_id = Some(ThreadId::new());
|
||||
chat.queued_user_messages.push_back(UserMessage {
|
||||
text: "queued follow up".to_string(),
|
||||
local_images: Vec::new(),
|
||||
remote_image_urls: Vec::new(),
|
||||
text_elements: Vec::new(),
|
||||
mention_bindings: Vec::new(),
|
||||
});
|
||||
|
||||
chat.maybe_send_next_queued_input();
|
||||
|
||||
match next_submit_op(&mut op_rx) {
|
||||
Op::UserTurn {
|
||||
submission_type: Some(SubmissionType::PromptQueued),
|
||||
..
|
||||
} => {}
|
||||
other => panic!("expected queued prompt submission, got {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn remap_placeholders_uses_attachment_labels() {
|
||||
let placeholder_one = "[Image #1]";
|
||||
|
||||
Reference in New Issue
Block a user