mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
feat(app-server): add optional turn_id to thread/fork (#30277)
## Description This adds stable optional `turnId` support to `thread/fork`. When supplied, the fork copies persisted history through that terminal turn, inclusive, and drops later turns from the new thread. Omitting or passing `null` preserves the existing full-history fork behavior, including the interruption marker when the stored source history ends mid-turn. ## Why We're deprecating `thread/rollback` and this will help certain UX use cases work around it by using `thread/fork` + `turn_id` instead.
This commit is contained in:
+8
-1
@@ -3673,6 +3673,13 @@
|
||||
}
|
||||
],
|
||||
"description": "Optional client-supplied analytics source classification for this forked thread."
|
||||
},
|
||||
"lastTurnId": {
|
||||
"description": "Optional last turn id to fork through, inclusive.\n\nWhen specified, turns after `last_turn_id` are omitted from the fork. The referenced turn cannot be in progress.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -6866,4 +6873,4 @@
|
||||
}
|
||||
],
|
||||
"title": "ClientRequest"
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -17287,6 +17287,13 @@
|
||||
}
|
||||
],
|
||||
"description": "Optional client-supplied analytics source classification for this forked thread."
|
||||
},
|
||||
"lastTurnId": {
|
||||
"description": "Optional last turn id to fork through, inclusive.\n\nWhen specified, turns after `last_turn_id` are omitted from the fork. The referenced turn cannot be in progress.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -20833,4 +20840,4 @@
|
||||
},
|
||||
"title": "CodexAppServerProtocol",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -15066,6 +15066,13 @@
|
||||
}
|
||||
],
|
||||
"description": "Optional client-supplied analytics source classification for this forked thread."
|
||||
},
|
||||
"lastTurnId": {
|
||||
"description": "Optional last turn id to fork through, inclusive.\n\nWhen specified, turns after `last_turn_id` are omitted from the fork. The referenced turn cannot be in progress.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -18611,4 +18618,4 @@
|
||||
},
|
||||
"title": "CodexAppServerProtocolV2",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,6 +168,13 @@
|
||||
}
|
||||
],
|
||||
"description": "Optional client-supplied analytics source classification for this forked thread."
|
||||
},
|
||||
"lastTurnId": {
|
||||
"description": "Optional last turn id to fork through, inclusive.\n\nWhen specified, turns after `last_turn_id` are omitted from the fork. The referenced turn cannot be in progress.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -175,4 +182,4 @@
|
||||
],
|
||||
"title": "ThreadForkParams",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,12 @@ import type { ThreadSource } from "./ThreadSource";
|
||||
* Prefer using thread_id whenever possible.
|
||||
*/
|
||||
export type ThreadForkParams = {threadId: string, /**
|
||||
* Optional last turn id to fork through, inclusive.
|
||||
*
|
||||
* When specified, turns after `last_turn_id` are omitted from the fork.
|
||||
* The referenced turn cannot be in progress.
|
||||
*/
|
||||
lastTurnId?: string | null, /**
|
||||
* Configuration overrides for the forked thread, if any.
|
||||
*/
|
||||
model?: string | null, modelProvider?: string | null, serviceTier?: string | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, /**
|
||||
|
||||
@@ -839,6 +839,30 @@ fn thread_path_params_deserialize_empty_path_as_none() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn thread_fork_last_turn_id_round_trips() {
|
||||
let params: ThreadForkParams = serde_json::from_value(json!({
|
||||
"threadId": "thread-1",
|
||||
"lastTurnId": "turn-2",
|
||||
}))
|
||||
.expect("thread/fork params deserialize");
|
||||
|
||||
assert_eq!(params.last_turn_id, Some("turn-2".to_string()));
|
||||
let serialized = serde_json::to_value(params).expect("thread/fork params serialize");
|
||||
assert_eq!(serialized["lastTurnId"], json!("turn-2"));
|
||||
|
||||
let omitted = serde_json::to_value(ThreadForkParams {
|
||||
thread_id: "thread-1".to_string(),
|
||||
..Default::default()
|
||||
})
|
||||
.expect("thread/fork params without last turn id serialize");
|
||||
assert_eq!(
|
||||
omitted["lastTurnId"],
|
||||
serde_json::Value::Null,
|
||||
"optional lastTurnId should serialize as null when omitted"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fs_get_metadata_response_round_trips_minimal_fields() {
|
||||
let response = FsGetMetadataResponse {
|
||||
|
||||
@@ -494,6 +494,13 @@ impl From<ThreadTurnsListResponse> for TurnsPage {
|
||||
pub struct ThreadForkParams {
|
||||
pub thread_id: String,
|
||||
|
||||
/// Optional last turn id to fork through, inclusive.
|
||||
///
|
||||
/// When specified, turns after `last_turn_id` are omitted from the fork.
|
||||
/// The referenced turn cannot be in progress.
|
||||
#[ts(optional = nullable)]
|
||||
pub last_turn_id: Option<String>,
|
||||
|
||||
/// [UNSTABLE] Specify the rollout path to fork from.
|
||||
/// If specified, the thread_id param will be ignored.
|
||||
#[experimental("thread/fork.path")]
|
||||
|
||||
Reference in New Issue
Block a user