mirror of
https://github.com/openai/codex.git
synced 2026-10-28 18:58:46 +00:00
add session ID everywhere
This commit is contained in:
@@ -148,6 +148,7 @@ fn sample_thread_start_response(
|
||||
model: &str,
|
||||
) -> ClientResponsePayload {
|
||||
ClientResponsePayload::ThreadStart(ThreadStartResponse {
|
||||
session_id: format!("session-{thread_id}"),
|
||||
thread: sample_thread(thread_id, ephemeral),
|
||||
model: model.to_string(),
|
||||
model_provider: "openai".to_string(),
|
||||
@@ -202,6 +203,7 @@ fn sample_thread_resume_response_with_source(
|
||||
source: AppServerSessionSource,
|
||||
) -> ClientResponsePayload {
|
||||
ClientResponsePayload::ThreadResume(ThreadResumeResponse {
|
||||
session_id: format!("session-{thread_id}"),
|
||||
thread: sample_thread_with_source(thread_id, ephemeral, source),
|
||||
model: model.to_string(),
|
||||
model_provider: "openai".to_string(),
|
||||
|
||||
@@ -101,6 +101,7 @@ fn sample_permission_profile() -> AppServerPermissionProfile {
|
||||
|
||||
fn sample_thread_start_response() -> ClientResponsePayload {
|
||||
ClientResponsePayload::ThreadStart(ThreadStartResponse {
|
||||
session_id: "session-1".to_string(),
|
||||
thread: sample_thread("thread-1"),
|
||||
model: "gpt-5".to_string(),
|
||||
model_provider: "openai".to_string(),
|
||||
@@ -118,6 +119,7 @@ fn sample_thread_start_response() -> ClientResponsePayload {
|
||||
|
||||
fn sample_thread_resume_response() -> ClientResponsePayload {
|
||||
ClientResponsePayload::ThreadResume(ThreadResumeResponse {
|
||||
session_id: "session-2".to_string(),
|
||||
thread: sample_thread("thread-2"),
|
||||
model: "gpt-5".to_string(),
|
||||
model_provider: "openai".to_string(),
|
||||
|
||||
+10
@@ -16754,6 +16754,11 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"sessionId": {
|
||||
"default": "",
|
||||
"description": "Session id shared by threads that belong to the same session tree.",
|
||||
"type": "string"
|
||||
},
|
||||
"thread": {
|
||||
"$ref": "#/definitions/v2/Thread"
|
||||
}
|
||||
@@ -17058,6 +17063,11 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"sessionId": {
|
||||
"default": "",
|
||||
"description": "Session id shared by threads that belong to the same session tree.",
|
||||
"type": "string"
|
||||
},
|
||||
"thread": {
|
||||
"$ref": "#/definitions/v2/Thread"
|
||||
}
|
||||
|
||||
+10
@@ -14640,6 +14640,11 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"sessionId": {
|
||||
"default": "",
|
||||
"description": "Session id shared by threads that belong to the same session tree.",
|
||||
"type": "string"
|
||||
},
|
||||
"thread": {
|
||||
"$ref": "#/definitions/Thread"
|
||||
}
|
||||
@@ -14944,6 +14949,11 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"sessionId": {
|
||||
"default": "",
|
||||
"description": "Session id shared by threads that belong to the same session tree.",
|
||||
"type": "string"
|
||||
},
|
||||
"thread": {
|
||||
"$ref": "#/definitions/Thread"
|
||||
}
|
||||
|
||||
@@ -2566,6 +2566,11 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"sessionId": {
|
||||
"default": "",
|
||||
"description": "Session id shared by threads that belong to the same session tree.",
|
||||
"type": "string"
|
||||
},
|
||||
"thread": {
|
||||
"$ref": "#/definitions/Thread"
|
||||
}
|
||||
|
||||
@@ -2566,6 +2566,11 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"sessionId": {
|
||||
"default": "",
|
||||
"description": "Session id shared by threads that belong to the same session tree.",
|
||||
"type": "string"
|
||||
},
|
||||
"thread": {
|
||||
"$ref": "#/definitions/Thread"
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@ import type { AskForApproval } from "./AskForApproval";
|
||||
import type { SandboxPolicy } from "./SandboxPolicy";
|
||||
import type { Thread } from "./Thread";
|
||||
|
||||
export type ThreadResumeResponse = {thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: AbsolutePathBuf, /**
|
||||
export type ThreadResumeResponse = {/**
|
||||
* Session id shared by threads that belong to the same session tree.
|
||||
*/
|
||||
sessionId: string, thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: AbsolutePathBuf, /**
|
||||
* Instruction source files currently loaded for this thread.
|
||||
*/
|
||||
instructionSources: Array<AbsolutePathBuf>, approvalPolicy: AskForApproval, /**
|
||||
|
||||
@@ -9,7 +9,10 @@ import type { AskForApproval } from "./AskForApproval";
|
||||
import type { SandboxPolicy } from "./SandboxPolicy";
|
||||
import type { Thread } from "./Thread";
|
||||
|
||||
export type ThreadStartResponse = {thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: AbsolutePathBuf, /**
|
||||
export type ThreadStartResponse = {/**
|
||||
* Session id shared by threads that belong to the same session tree.
|
||||
*/
|
||||
sessionId: string, thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: AbsolutePathBuf, /**
|
||||
* Instruction source files currently loaded for this thread.
|
||||
*/
|
||||
instructionSources: Array<AbsolutePathBuf>, approvalPolicy: AskForApproval, /**
|
||||
|
||||
@@ -2126,6 +2126,7 @@ mod tests {
|
||||
let response = ClientResponse::ThreadStart {
|
||||
request_id: RequestId::Integer(7),
|
||||
response: v2::ThreadStartResponse {
|
||||
session_id: "67e55044-10b1-426f-9247-bb680e5fe0c7".to_string(),
|
||||
thread: v2::Thread {
|
||||
id: "67e55044-10b1-426f-9247-bb680e5fe0c8".to_string(),
|
||||
forked_from_id: None,
|
||||
@@ -2166,6 +2167,7 @@ mod tests {
|
||||
"method": "thread/start",
|
||||
"id": 7,
|
||||
"response": {
|
||||
"sessionId": "67e55044-10b1-426f-9247-bb680e5fe0c7",
|
||||
"thread": {
|
||||
"id": "67e55044-10b1-426f-9247-bb680e5fe0c8",
|
||||
"forkedFromId": null,
|
||||
|
||||
@@ -3638,6 +3638,9 @@ pub struct MockExperimentalMethodResponse {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadStartResponse {
|
||||
/// Session id shared by threads that belong to the same session tree.
|
||||
#[serde(default)]
|
||||
pub session_id: String,
|
||||
pub thread: Thread,
|
||||
pub model: String,
|
||||
pub model_provider: String,
|
||||
@@ -3752,6 +3755,9 @@ pub struct ThreadResumeParams {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadResumeResponse {
|
||||
/// Session id shared by threads that belong to the same session tree.
|
||||
#[serde(default)]
|
||||
pub session_id: String,
|
||||
pub thread: Thread,
|
||||
pub model: String,
|
||||
pub model_provider: String,
|
||||
|
||||
@@ -2931,6 +2931,7 @@ impl CodexMessageProcessor {
|
||||
);
|
||||
|
||||
let response = ThreadStartResponse {
|
||||
session_id: session_configured.session_id.to_string(),
|
||||
thread: thread.clone(),
|
||||
model: config_snapshot.model,
|
||||
model_provider: config_snapshot.model_provider_id,
|
||||
@@ -4472,6 +4473,7 @@ impl CodexMessageProcessor {
|
||||
);
|
||||
|
||||
let response = ThreadResumeResponse {
|
||||
session_id: session_configured.session_id.to_string(),
|
||||
thread,
|
||||
model: session_configured.model,
|
||||
model_provider: session_configured.model_provider_id,
|
||||
@@ -8477,8 +8479,10 @@ async fn handle_pending_thread_resume_request(
|
||||
let sandbox = thread_response_sandbox_policy(&permission_profile, cwd.as_path());
|
||||
let active_permission_profile =
|
||||
thread_response_active_permission_profile(active_permission_profile);
|
||||
let session_id = conversation.session_configured().session_id.to_string();
|
||||
|
||||
let response = ThreadResumeResponse {
|
||||
session_id,
|
||||
thread,
|
||||
model,
|
||||
model_provider: model_provider_id,
|
||||
|
||||
@@ -263,7 +263,10 @@ async fn thread_resume_tracks_thread_initialized_analytics() -> Result<()> {
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(resume_id)),
|
||||
)
|
||||
.await??;
|
||||
let ThreadResumeResponse { thread, .. } = to_response::<ThreadResumeResponse>(resume_resp)?;
|
||||
let ThreadResumeResponse {
|
||||
session_id, thread, ..
|
||||
} = to_response::<ThreadResumeResponse>(resume_resp)?;
|
||||
assert!(!session_id.is_empty(), "session id should not be empty");
|
||||
|
||||
let payload = wait_for_analytics_payload(&server, DEFAULT_READ_TIMEOUT).await?;
|
||||
let event = thread_initialized_event(&payload)?;
|
||||
|
||||
@@ -78,10 +78,12 @@ async fn thread_start_creates_thread_and_emits_started() -> Result<()> {
|
||||
.await??;
|
||||
let resp_result = resp.result.clone();
|
||||
let ThreadStartResponse {
|
||||
session_id,
|
||||
thread,
|
||||
model_provider,
|
||||
..
|
||||
} = to_response::<ThreadStartResponse>(resp)?;
|
||||
assert!(!session_id.is_empty(), "session id should not be empty");
|
||||
assert!(!thread.id.is_empty(), "thread id should not be empty");
|
||||
assert!(
|
||||
thread.preview.is_empty(),
|
||||
|
||||
@@ -381,7 +381,7 @@ impl CodexThread {
|
||||
self.rollout_path.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn session_configured(&self) -> SessionConfiguredEvent {
|
||||
pub fn session_configured(&self) -> SessionConfiguredEvent {
|
||||
self.session_configured.clone()
|
||||
}
|
||||
|
||||
|
||||
@@ -1052,6 +1052,7 @@ fn session_configured_from_thread_start_response(
|
||||
config: &Config,
|
||||
) -> Result<SessionConfiguredEvent, String> {
|
||||
session_configured_from_thread_response(
|
||||
&response.session_id,
|
||||
&response.thread.id,
|
||||
response.thread.name.clone(),
|
||||
response.thread.path.clone(),
|
||||
@@ -1076,6 +1077,7 @@ fn session_configured_from_thread_resume_response(
|
||||
config: &Config,
|
||||
) -> Result<SessionConfiguredEvent, String> {
|
||||
session_configured_from_thread_response(
|
||||
&response.session_id,
|
||||
&response.thread.id,
|
||||
response.thread.name.clone(),
|
||||
response.thread.path.clone(),
|
||||
@@ -1109,6 +1111,7 @@ fn review_target_to_api(target: ReviewTarget) -> ApiReviewTarget {
|
||||
reason = "session mapping keeps explicit fields"
|
||||
)]
|
||||
fn session_configured_from_thread_response(
|
||||
session_id: &str,
|
||||
thread_id: &str,
|
||||
thread_name: Option<String>,
|
||||
rollout_path: Option<PathBuf>,
|
||||
@@ -1122,11 +1125,13 @@ fn session_configured_from_thread_response(
|
||||
cwd: AbsolutePathBuf,
|
||||
reasoning_effort: Option<codex_protocol::openai_models::ReasoningEffort>,
|
||||
) -> Result<SessionConfiguredEvent, String> {
|
||||
let session_id = SessionId::from_string(session_id)
|
||||
.map_err(|err| format!("session id `{session_id}` is invalid: {err}"))?;
|
||||
let thread_id = ThreadId::from_string(thread_id)
|
||||
.map_err(|err| format!("thread id `{thread_id}` is invalid: {err}"))?;
|
||||
|
||||
Ok(SessionConfiguredEvent {
|
||||
session_id: SessionId::from(thread_id),
|
||||
session_id,
|
||||
thread_id,
|
||||
forked_from_id: None,
|
||||
thread_name,
|
||||
|
||||
@@ -437,6 +437,14 @@ async fn session_configured_from_thread_response_uses_review_policy_from_respons
|
||||
let event = session_configured_from_thread_start_response(&response, &config)
|
||||
.expect("build bootstrap session configured event");
|
||||
|
||||
assert_eq!(
|
||||
event.session_id.to_string(),
|
||||
"67e55044-10b1-426f-9247-bb680e5fe0c7"
|
||||
);
|
||||
assert_eq!(
|
||||
event.thread_id.to_string(),
|
||||
"67e55044-10b1-426f-9247-bb680e5fe0c8"
|
||||
);
|
||||
assert_eq!(event.approvals_reviewer, ApprovalsReviewer::AutoReview);
|
||||
}
|
||||
|
||||
@@ -461,6 +469,7 @@ async fn session_configured_from_thread_response_uses_permission_profile_from_re
|
||||
|
||||
fn sample_thread_start_response() -> ThreadStartResponse {
|
||||
ThreadStartResponse {
|
||||
session_id: "67e55044-10b1-426f-9247-bb680e5fe0c7".to_string(),
|
||||
thread: codex_app_server_protocol::Thread {
|
||||
id: "67e55044-10b1-426f-9247-bb680e5fe0c8".to_string(),
|
||||
forked_from_id: None,
|
||||
|
||||
@@ -296,7 +296,7 @@ mod tests {
|
||||
let event = Event {
|
||||
id: "1".to_string(),
|
||||
msg: EventMsg::SessionConfigured(SessionConfiguredEvent {
|
||||
session_id: codex_protocol::SessionId::from(thread_id),
|
||||
session_id: codex_protocol::SessionId::new(),
|
||||
thread_id,
|
||||
forked_from_id: None,
|
||||
thread_name: None,
|
||||
@@ -342,7 +342,7 @@ mod tests {
|
||||
let thread_id = ThreadId::new();
|
||||
let rollout_file = NamedTempFile::new()?;
|
||||
let session_configured_event = SessionConfiguredEvent {
|
||||
session_id: codex_protocol::SessionId::from(thread_id),
|
||||
session_id: codex_protocol::SessionId::new(),
|
||||
thread_id,
|
||||
forked_from_id: None,
|
||||
thread_name: None,
|
||||
@@ -412,7 +412,7 @@ mod tests {
|
||||
let thread_id = ThreadId::new();
|
||||
let rollout_file = NamedTempFile::new()?;
|
||||
let session_configured_event = SessionConfiguredEvent {
|
||||
session_id: codex_protocol::SessionId::from(thread_id),
|
||||
session_id: codex_protocol::SessionId::new(),
|
||||
thread_id,
|
||||
forked_from_id: None,
|
||||
thread_name: None,
|
||||
|
||||
@@ -1791,6 +1791,7 @@ mod tests {
|
||||
let forked_from_id = ThreadId::new();
|
||||
let read_only_profile = PermissionProfile::read_only();
|
||||
let response = ThreadResumeResponse {
|
||||
session_id: ThreadId::new().to_string(),
|
||||
thread: codex_app_server_protocol::Thread {
|
||||
id: thread_id.to_string(),
|
||||
forked_from_id: Some(forked_from_id.to_string()),
|
||||
|
||||
Reference in New Issue
Block a user