add session ID everywhere

This commit is contained in:
jif-oai
2026-05-01 12:18:36 +01:00
parent 0ec3159b70
commit 85f522a73e
18 changed files with 80 additions and 8 deletions
@@ -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(),
+2
View File
@@ -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(),
@@ -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"
}
@@ -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(),
+1 -1
View File
@@ -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()
}
+6 -1
View File
@@ -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,
+9
View File
@@ -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,
+3 -3
View File
@@ -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,
+1
View File
@@ -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()),