add stub handlers in message processor and fix list models test

This commit is contained in:
Owen Lin
2025-11-01 11:02:59 -07:00
parent 276c7fbb5d
commit 62be8a3cde
2 changed files with 85 additions and 15 deletions

View File

@@ -56,6 +56,7 @@ use codex_app_server_protocol::ServerRequestPayload;
use codex_app_server_protocol::SessionConfiguredNotification;
use codex_app_server_protocol::SetDefaultModelParams;
use codex_app_server_protocol::SetDefaultModelResponse;
use codex_app_server_protocol::SortOrder;
use codex_app_server_protocol::UserInfoResponse;
use codex_app_server_protocol::UserSavedConfig;
use codex_backend_client::Client as BackendClient;
@@ -174,6 +175,56 @@ impl CodexMessageProcessor {
ClientRequest::Initialize { .. } => {
panic!("Initialize should be handled in MessageProcessor");
}
// === v2 Thread/Turn APIs (stubs) ===
ClientRequest::ThreadStart {
request_id,
params: _,
} => {
self.send_unimplemented_error(request_id, "thread/start")
.await;
}
ClientRequest::ThreadResume {
request_id,
params: _,
} => {
self.send_unimplemented_error(request_id, "thread/resume")
.await;
}
ClientRequest::ThreadArchive {
request_id,
params: _,
} => {
self.send_unimplemented_error(request_id, "thread/archive")
.await;
}
ClientRequest::ThreadList {
request_id,
params: _,
} => {
self.send_unimplemented_error(request_id, "thread/list")
.await;
}
ClientRequest::ThreadCompact {
request_id,
params: _,
} => {
self.send_unimplemented_error(request_id, "thread/compact")
.await;
}
ClientRequest::TurnStart {
request_id,
params: _,
} => {
self.send_unimplemented_error(request_id, "turn/start")
.await;
}
ClientRequest::TurnInterrupt {
request_id,
params: _,
} => {
self.send_unimplemented_error(request_id, "turn/interrupt")
.await;
}
ClientRequest::NewConversation { request_id, params } => {
// Do not tokio::spawn() to process new_conversation()
// asynchronously because we need to ensure the conversation is
@@ -953,20 +1004,34 @@ impl CodexMessageProcessor {
}
async fn list_models(&self, request_id: RequestId, params: ModelListParams) {
let ModelListParams { page_size, cursor } = params;
let models = supported_models();
let ModelListParams {
cursor,
limit,
order,
} = params;
let mut models = supported_models();
// Sort models according to requested order; default to descending.
match order.unwrap_or(SortOrder::Desc) {
SortOrder::Asc => models.sort_by(|a, b| a.id.cmp(&b.id)),
SortOrder::Desc => models.sort_by(|a, b| b.id.cmp(&a.id)),
}
let total = models.len();
if total == 0 {
let response = ModelListResponse {
items: Vec::new(),
data: Vec::new(),
next_cursor: None,
};
self.outgoing.send_response(request_id, response).await;
return;
}
let effective_page_size = page_size.unwrap_or(total).max(1).min(total);
// Determine pagination window
let default_limit = total as i32;
let effective_limit = limit.unwrap_or(default_limit).max(1).min(default_limit) as usize;
let start = match cursor {
Some(cursor) => match cursor.parse::<usize>() {
Ok(idx) => idx,
@@ -993,14 +1058,15 @@ impl CodexMessageProcessor {
return;
}
let end = start.saturating_add(effective_page_size).min(total);
let items = models[start..end].to_vec();
let end = start.saturating_add(effective_limit).min(total);
let data = models[start..end].to_vec();
let next_cursor = if end < total {
Some(end.to_string())
} else {
None
};
let response = ModelListResponse { items, next_cursor };
let response = ModelListResponse { data, next_cursor };
self.outgoing.send_response(request_id, response).await;
}

View File

@@ -28,8 +28,9 @@ async fn list_models_returns_all_models_with_large_limit() -> Result<()> {
let request_id = mcp
.send_list_models_request(ModelListParams {
page_size: Some(100),
cursor: None,
limit: Some(100),
order: None,
})
.await?;
@@ -39,7 +40,7 @@ async fn list_models_returns_all_models_with_large_limit() -> Result<()> {
)
.await??;
let ModelListResponse { items, next_cursor } = to_response::<ModelListResponse>(response)?;
let ModelListResponse { data, next_cursor } = to_response::<ModelListResponse>(response)?;
let expected_models = vec![
Model {
@@ -98,7 +99,7 @@ async fn list_models_returns_all_models_with_large_limit() -> Result<()> {
},
];
assert_eq!(items, expected_models);
assert_eq!(data, expected_models);
assert!(next_cursor.is_none());
Ok(())
}
@@ -112,8 +113,9 @@ async fn list_models_pagination_works() -> Result<()> {
let first_request = mcp
.send_list_models_request(ModelListParams {
page_size: Some(1),
cursor: None,
limit: Some(1),
order: None,
})
.await?;
@@ -124,7 +126,7 @@ async fn list_models_pagination_works() -> Result<()> {
.await??;
let ModelListResponse {
items: first_items,
data: first_items,
next_cursor: first_cursor,
} = to_response::<ModelListResponse>(first_response)?;
@@ -134,8 +136,9 @@ async fn list_models_pagination_works() -> Result<()> {
let second_request = mcp
.send_list_models_request(ModelListParams {
page_size: Some(1),
cursor: Some(next_cursor.clone()),
limit: Some(1),
order: None,
})
.await?;
@@ -146,7 +149,7 @@ async fn list_models_pagination_works() -> Result<()> {
.await??;
let ModelListResponse {
items: second_items,
data: second_items,
next_cursor: second_cursor,
} = to_response::<ModelListResponse>(second_response)?;
@@ -165,8 +168,9 @@ async fn list_models_rejects_invalid_cursor() -> Result<()> {
let request_id = mcp
.send_list_models_request(ModelListParams {
page_size: None,
cursor: Some("invalid".to_string()),
limit: None,
order: None,
})
.await?;