mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
feat(app-server): thread/turns/items/list -> thread/items/list (#29705)
## Description Rename the experimental app-server item pagination API from `thread/turns/items/list` to `thread/items/list` and make `turnId` optional. Clients can now page persisted items across a thread, or still filter to one turn when needed. ## What changed - Rename the request/response protocol types and JSON-RPC method to `ThreadItemsList*` / `thread/items/list`. - Pass optional `turnId` through to `ThreadStore::list_items`. - Update app-server docs and focused protocol/app-server tests. ## Validation - `just test -p codex-app-server-protocol thread_items_list_round_trips` - `just test -p codex-app-server thread_items_list_returns_unsupported`
This commit is contained in:
committed by
GitHub
Unverified
parent
66f0220c56
commit
1882719b30
@@ -1223,8 +1223,8 @@ impl MessageProcessor {
|
||||
ClientRequest::ThreadTurnsList { params, .. } => {
|
||||
self.thread_processor.thread_turns_list(params).await
|
||||
}
|
||||
ClientRequest::ThreadTurnsItemsList { params, .. } => {
|
||||
self.thread_processor.thread_turns_items_list(params).await
|
||||
ClientRequest::ThreadItemsList { params, .. } => {
|
||||
self.thread_processor.thread_items_list(params).await
|
||||
}
|
||||
ClientRequest::ThreadShellCommand { params, .. } => {
|
||||
self.thread_processor
|
||||
|
||||
@@ -211,6 +211,8 @@ use codex_app_server_protocol::ThreadIncrementElicitationResponse;
|
||||
use codex_app_server_protocol::ThreadInjectItemsParams;
|
||||
use codex_app_server_protocol::ThreadInjectItemsResponse;
|
||||
use codex_app_server_protocol::ThreadItem;
|
||||
use codex_app_server_protocol::ThreadItemsListParams;
|
||||
use codex_app_server_protocol::ThreadItemsListResponse;
|
||||
use codex_app_server_protocol::ThreadListCwdFilter;
|
||||
use codex_app_server_protocol::ThreadListParams;
|
||||
use codex_app_server_protocol::ThreadListResponse;
|
||||
@@ -256,7 +258,6 @@ use codex_app_server_protocol::ThreadStartParams;
|
||||
use codex_app_server_protocol::ThreadStartResponse;
|
||||
use codex_app_server_protocol::ThreadStartedNotification;
|
||||
use codex_app_server_protocol::ThreadStatus;
|
||||
use codex_app_server_protocol::ThreadTurnsItemsListParams;
|
||||
use codex_app_server_protocol::ThreadTurnsListParams;
|
||||
use codex_app_server_protocol::ThreadTurnsListResponse;
|
||||
use codex_app_server_protocol::ThreadUnarchiveParams;
|
||||
@@ -436,6 +437,7 @@ use codex_state::log_db::LogDbLayer;
|
||||
use codex_thread_store::ArchiveThreadParams as StoreArchiveThreadParams;
|
||||
use codex_thread_store::DeleteThreadParams as StoreDeleteThreadParams;
|
||||
use codex_thread_store::GitInfoPatch as StoreGitInfoPatch;
|
||||
use codex_thread_store::ListItemsParams as StoreListItemsParams;
|
||||
use codex_thread_store::ListThreadsParams as StoreListThreadsParams;
|
||||
use codex_thread_store::LocalThreadStore;
|
||||
use codex_thread_store::ReadThreadByRolloutPathParams as StoreReadThreadByRolloutPathParams;
|
||||
|
||||
@@ -683,13 +683,13 @@ impl ThreadRequestProcessor {
|
||||
.map(|response| Some(response.into()))
|
||||
}
|
||||
|
||||
pub(crate) async fn thread_turns_items_list(
|
||||
pub(crate) async fn thread_items_list(
|
||||
&self,
|
||||
_params: ThreadTurnsItemsListParams,
|
||||
params: ThreadItemsListParams,
|
||||
) -> Result<Option<ClientResponsePayload>, JSONRPCErrorError> {
|
||||
Err(method_not_found(
|
||||
"thread/turns/items/list is not supported yet",
|
||||
))
|
||||
self.thread_items_list_response_inner(params)
|
||||
.await
|
||||
.map(|response| Some(response.into()))
|
||||
}
|
||||
|
||||
pub(crate) async fn thread_shell_command(
|
||||
@@ -2388,6 +2388,68 @@ impl ThreadRequestProcessor {
|
||||
)
|
||||
}
|
||||
|
||||
async fn thread_items_list_response_inner(
|
||||
&self,
|
||||
params: ThreadItemsListParams,
|
||||
) -> Result<ThreadItemsListResponse, JSONRPCErrorError> {
|
||||
let ThreadItemsListParams {
|
||||
thread_id,
|
||||
turn_id,
|
||||
cursor,
|
||||
limit,
|
||||
sort_direction,
|
||||
} = params;
|
||||
let thread_id = ThreadId::from_string(&thread_id)
|
||||
.map_err(|err| invalid_request(format!("invalid thread id: {err}")))?;
|
||||
let page_size = limit
|
||||
.map(|value| value as usize)
|
||||
.unwrap_or(THREAD_ITEMS_DEFAULT_LIMIT)
|
||||
.clamp(1, THREAD_ITEMS_MAX_LIMIT);
|
||||
let page = self
|
||||
.thread_store
|
||||
.list_items(StoreListItemsParams {
|
||||
thread_id,
|
||||
turn_id,
|
||||
include_archived: true,
|
||||
cursor,
|
||||
page_size,
|
||||
sort_direction: match sort_direction.unwrap_or(SortDirection::Asc) {
|
||||
SortDirection::Asc => StoreSortDirection::Asc,
|
||||
SortDirection::Desc => StoreSortDirection::Desc,
|
||||
},
|
||||
})
|
||||
.await
|
||||
.map_err(|err| match err {
|
||||
ThreadStoreError::InvalidRequest { message } => invalid_request(message),
|
||||
ThreadStoreError::Unsupported { .. } => {
|
||||
method_not_found("thread/items/list is not supported yet")
|
||||
}
|
||||
ThreadStoreError::ThreadNotFound { thread_id } => {
|
||||
invalid_request(format!("no rollout found for thread id {thread_id}"))
|
||||
}
|
||||
err => internal_error(format!("failed to list thread items: {err}")),
|
||||
})?;
|
||||
let data =
|
||||
page.items
|
||||
.into_iter()
|
||||
.map(|item| {
|
||||
serde_json::from_slice::<ThreadItem>(&item.materialized_thread_item_json)
|
||||
.map_err(|err| {
|
||||
internal_error(format!(
|
||||
"failed to deserialize stored thread item {}: {err}",
|
||||
item.item_key
|
||||
))
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(ThreadItemsListResponse {
|
||||
data,
|
||||
next_cursor: page.next_cursor,
|
||||
backwards_cursor: page.backwards_cursor,
|
||||
})
|
||||
}
|
||||
|
||||
async fn load_thread_turns_list_history(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
@@ -3714,6 +3776,8 @@ fn xcode_26_4_mcp_elicitations_auto_deny(
|
||||
|
||||
const THREAD_TURNS_DEFAULT_LIMIT: usize = 25;
|
||||
const THREAD_TURNS_MAX_LIMIT: usize = 100;
|
||||
const THREAD_ITEMS_DEFAULT_LIMIT: usize = 25;
|
||||
const THREAD_ITEMS_MAX_LIMIT: usize = 100;
|
||||
|
||||
fn thread_backwards_cursor_for_sort_key(
|
||||
thread: &StoredThread,
|
||||
|
||||
Reference in New Issue
Block a user