mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
store and expose parent_thread_id on Threads (#25113)
## Why This PR https://github.com/openai/codex/pull/24161#discussion_r3325692763 revealed a subagent data modeling issue, where we overloaded `forked_from_id` to also mean `parent_thread_id`. That's incorrect since guardian and review subagents can be a subagent and NOT fork the main thread's history. The solution here is to explicitly store a new `parent_thread_id` on `SessionMeta`, alongside `forked_from_id` which already exists. While we're at it, also expose it in the app-server protocol on the `Thread` object. A thread->subagent relationship and a fork of thread history are orthogonal concepts. ## What Changed - Added top-level `parent_thread_id` persistence on `SessionMeta` and runtime/session plumbing through `SessionConfiguredEvent`, `CodexSpawnArgs`, `SessionConfiguration`, `ThreadConfigSnapshot`, `TurnContext`, and `ModelClient`. - Made turn metadata, request headers, analytics, and subagent-start events read the separate runtime/top-level parent field instead of deriving general parent lineage from `SessionSource` or `forked_from_thread_id`. - Passed parent lineage separately at delegated subagent, review, guardian, agent-job, and multi-agent spawn construction sites; copied-history fork lineage remains derived only from `InitialHistory`. - Persisted and exposed parent lineage through rollout/thread-store projections and app-server v2 `Thread.parentThreadId`. - Updated app-server README text and regenerated app-server schema fixtures for the additive `parentThreadId` response field.
This commit is contained in:
committed by
GitHub
Unverified
parent
3b7334d099
commit
cf0911076f
@@ -2451,6 +2451,11 @@ impl InitialHistory {
|
||||
.and_then(|meta| meta.thread_source)
|
||||
}
|
||||
|
||||
pub fn get_resumed_parent_thread_id(&self) -> Option<ThreadId> {
|
||||
self.get_resumed_session_meta()
|
||||
.and_then(|meta| meta.parent_thread_id)
|
||||
}
|
||||
|
||||
fn get_resumed_session_meta(&self) -> Option<&SessionMeta> {
|
||||
match self {
|
||||
InitialHistory::New | InitialHistory::Cleared | InitialHistory::Forked(_) => None,
|
||||
@@ -2716,6 +2721,8 @@ pub struct SessionMeta {
|
||||
pub id: ThreadId,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub forked_from_id: Option<ThreadId>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub parent_thread_id: Option<ThreadId>,
|
||||
pub timestamp: String,
|
||||
pub cwd: PathBuf,
|
||||
pub originator: String,
|
||||
@@ -2750,6 +2757,7 @@ impl Default for SessionMeta {
|
||||
SessionMeta {
|
||||
id: ThreadId::default(),
|
||||
forked_from_id: None,
|
||||
parent_thread_id: None,
|
||||
timestamp: String::new(),
|
||||
cwd: PathBuf::new(),
|
||||
originator: String::new(),
|
||||
@@ -3421,6 +3429,8 @@ pub struct SessionConfiguredEvent {
|
||||
pub thread_id: ThreadId,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub forked_from_id: Option<ThreadId>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub parent_thread_id: Option<ThreadId>,
|
||||
/// Optional analytics source classification for this thread.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub thread_source: Option<ThreadSource>,
|
||||
@@ -3490,6 +3500,7 @@ impl<'de> Deserialize<'de> for SessionConfiguredEvent {
|
||||
#[serde(default)]
|
||||
thread_id: Option<ThreadId>,
|
||||
forked_from_id: Option<ThreadId>,
|
||||
parent_thread_id: Option<ThreadId>,
|
||||
#[serde(default)]
|
||||
thread_source: Option<ThreadSource>,
|
||||
#[serde(default)]
|
||||
@@ -3530,6 +3541,7 @@ impl<'de> Deserialize<'de> for SessionConfiguredEvent {
|
||||
session_id: wire.session_id,
|
||||
thread_id: wire.thread_id.unwrap_or_else(|| wire.session_id.into()),
|
||||
forked_from_id: wire.forked_from_id,
|
||||
parent_thread_id: wire.parent_thread_id,
|
||||
thread_source: wire.thread_source,
|
||||
thread_name: wire.thread_name,
|
||||
model: wire.model,
|
||||
@@ -5329,6 +5341,7 @@ mod tests {
|
||||
session_id,
|
||||
thread_id,
|
||||
forked_from_id: None,
|
||||
parent_thread_id: None,
|
||||
thread_source: None,
|
||||
thread_name: None,
|
||||
model: "codex-mini-latest".to_string(),
|
||||
|
||||
Reference in New Issue
Block a user