mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Add subagent lineage metadata for responsesapi (#24161)
## Why We recently added `forked_from_thread_id` which lets us trace where a thread's _context_ comes from, but we also want to understand subagent lineage (e.g. which parent thread spawned this subagent? what kind of subagent is it?) which is orthogonal. This PR adds `parent_thread_id` and `subagent_kind` to the `x-codex-turn-metadata` header sent to ResponsesAPI. ## What changed - Adds `parent_thread_id` and `subagent_kind` to core-owned `x-codex-turn-metadata`. - Restores persisted `SessionSource` and `ThreadSource` from resumed session metadata so cold-resumed subagent threads keep their lineage on later Responses API requests. - Centralizes parent-thread extraction on `SessionSource` / `SubAgentSource` and reuses it in the Responses client, analytics, agent control, and state parsing paths. - Extends reserved-key, git-enrichment, thread-spawn, and app-server v2 metadata coverage for the new lineage fields. ## Verification - Not run locally per request. - Added focused coverage in `core/src/turn_metadata_tests.rs` and `app-server/tests/suite/v2/client_metadata.rs`.
This commit is contained in:
committed by
GitHub
Unverified
parent
62039e8d35
commit
fc9cf62efb
@@ -2440,12 +2440,22 @@ impl InitialHistory {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_resumed_session_sources(&self) -> Option<(SessionSource, Option<ThreadSource>)> {
|
||||
let meta = self.get_resumed_session_meta()?;
|
||||
Some((meta.source.clone(), meta.thread_source))
|
||||
}
|
||||
|
||||
pub fn get_resumed_thread_source(&self) -> Option<ThreadSource> {
|
||||
self.get_resumed_session_meta()
|
||||
.and_then(|meta| meta.thread_source)
|
||||
}
|
||||
|
||||
fn get_resumed_session_meta(&self) -> Option<&SessionMeta> {
|
||||
match self {
|
||||
InitialHistory::New | InitialHistory::Cleared | InitialHistory::Forked(_) => None,
|
||||
InitialHistory::Resumed(resumed) => {
|
||||
resumed.history.iter().find_map(|item| match item {
|
||||
RolloutItem::SessionMeta(meta_line) => meta_line.meta.thread_source,
|
||||
RolloutItem::SessionMeta(meta_line) => Some(&meta_line.meta),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
@@ -2630,6 +2640,19 @@ impl SessionSource {
|
||||
.restriction_product()
|
||||
.is_some_and(|product| product.matches_product_restriction(products))
|
||||
}
|
||||
|
||||
pub fn parent_thread_id(&self) -> Option<ThreadId> {
|
||||
match self {
|
||||
SessionSource::SubAgent(subagent_source) => subagent_source.parent_thread_id(),
|
||||
SessionSource::Cli
|
||||
| SessionSource::VSCode
|
||||
| SessionSource::Exec
|
||||
| SessionSource::Mcp
|
||||
| SessionSource::Custom(_)
|
||||
| SessionSource::Internal(_)
|
||||
| SessionSource::Unknown => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for SubAgentSource {
|
||||
@@ -2650,6 +2673,30 @@ impl fmt::Display for SubAgentSource {
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAgentSource {
|
||||
pub fn kind(&self) -> &str {
|
||||
match self {
|
||||
SubAgentSource::Review => "review",
|
||||
SubAgentSource::Compact => "compact",
|
||||
SubAgentSource::ThreadSpawn { .. } => "thread_spawn",
|
||||
SubAgentSource::MemoryConsolidation => "memory_consolidation",
|
||||
SubAgentSource::Other(other) => other,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parent_thread_id(&self) -> Option<ThreadId> {
|
||||
match self {
|
||||
SubAgentSource::ThreadSpawn {
|
||||
parent_thread_id, ..
|
||||
} => Some(*parent_thread_id),
|
||||
SubAgentSource::Review
|
||||
| SubAgentSource::Compact
|
||||
| SubAgentSource::MemoryConsolidation
|
||||
| SubAgentSource::Other(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for InternalSessionSource {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
|
||||
Reference in New Issue
Block a user