mirror of
https://github.com/openai/codex.git
synced 2026-11-09 20:50:33 +00:00
Add app-server toolSearch debug RPC
This commit is contained in:
@@ -1386,6 +1386,9 @@ impl MessageProcessor {
|
||||
.mcp_server_status_list(&request_id, params)
|
||||
.await
|
||||
}
|
||||
ClientRequest::ToolSearchSearch { params, .. } => {
|
||||
self.mcp_processor.tool_search_search(params).await
|
||||
}
|
||||
ClientRequest::McpResourceRead { params, .. } => {
|
||||
self.mcp_processor
|
||||
.mcp_resource_read(&request_id, params)
|
||||
|
||||
@@ -274,6 +274,9 @@ use codex_app_server_protocol::ThreadUnarchivedNotification;
|
||||
use codex_app_server_protocol::ThreadUnsubscribeParams;
|
||||
use codex_app_server_protocol::ThreadUnsubscribeResponse;
|
||||
use codex_app_server_protocol::ThreadUnsubscribeStatus;
|
||||
use codex_app_server_protocol::ToolSearchSearchParams;
|
||||
use codex_app_server_protocol::ToolSearchSearchResponse;
|
||||
use codex_app_server_protocol::ToolSearchSearchResult;
|
||||
use codex_app_server_protocol::Turn;
|
||||
use codex_app_server_protocol::TurnEnvironmentParams;
|
||||
use codex_app_server_protocol::TurnError;
|
||||
|
||||
@@ -53,6 +53,15 @@ impl McpRequestProcessor {
|
||||
.map(|()| None)
|
||||
}
|
||||
|
||||
pub(crate) async fn tool_search_search(
|
||||
&self,
|
||||
params: ToolSearchSearchParams,
|
||||
) -> Result<Option<ClientResponsePayload>, JSONRPCErrorError> {
|
||||
self.tool_search_search_response(params)
|
||||
.await
|
||||
.map(|response| Some(response.into()))
|
||||
}
|
||||
|
||||
pub(crate) async fn mcp_resource_read(
|
||||
&self,
|
||||
request_id: &ConnectionRequestId,
|
||||
@@ -109,6 +118,32 @@ impl McpRequestProcessor {
|
||||
Ok((thread_id, thread))
|
||||
}
|
||||
|
||||
async fn tool_search_search_response(
|
||||
&self,
|
||||
params: ToolSearchSearchParams,
|
||||
) -> Result<ToolSearchSearchResponse, JSONRPCErrorError> {
|
||||
let ToolSearchSearchParams {
|
||||
thread_id,
|
||||
query,
|
||||
limit,
|
||||
} = params;
|
||||
let query = query.trim();
|
||||
if query.is_empty() {
|
||||
return Err(invalid_request("query must not be empty"));
|
||||
}
|
||||
let limit = limit.unwrap_or(codex_tools::TOOL_SEARCH_DEFAULT_LIMIT as u32);
|
||||
if limit == 0 {
|
||||
return Err(invalid_request("limit must be greater than zero"));
|
||||
}
|
||||
|
||||
let (_, thread) = self.load_thread(&thread_id).await?;
|
||||
let result = thread
|
||||
.search_tool_search(query, limit as usize)
|
||||
.await
|
||||
.map_err(|err| internal_error(format!("failed to search tool_search: {err}")))?;
|
||||
tool_search_result_to_response(result)
|
||||
}
|
||||
|
||||
async fn mcp_server_oauth_login_response(
|
||||
&self,
|
||||
params: McpServerOauthLoginParams,
|
||||
@@ -475,6 +510,59 @@ impl McpRequestProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
fn tool_search_result_to_response(
|
||||
result: codex_core::ToolSearchDebugResult,
|
||||
) -> Result<ToolSearchSearchResponse, JSONRPCErrorError> {
|
||||
Ok(ToolSearchSearchResponse {
|
||||
indexed_tool_count: usize_to_u32(result.indexed_tool_count, "indexedToolCount")?,
|
||||
matching_tool_count: usize_to_u32(result.matching_tool_count, "matchingToolCount")?,
|
||||
requested_limit: usize_to_u32(result.requested_limit, "requestedLimit")?,
|
||||
effective_limit: usize_to_u32(result.effective_limit, "effectiveLimit")?,
|
||||
top_k_truncated: result.top_k_truncated,
|
||||
tools: serialize_tool_specs(result.tools)?,
|
||||
results: result
|
||||
.results
|
||||
.into_iter()
|
||||
.map(tool_search_result_entry_to_response)
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn tool_search_result_entry_to_response(
|
||||
result: codex_core::ToolSearchDebugResultEntry,
|
||||
) -> Result<ToolSearchSearchResult, JSONRPCErrorError> {
|
||||
Ok(ToolSearchSearchResult {
|
||||
rank: usize_to_u32(result.rank, "rank")?,
|
||||
index: usize_to_u32(result.index, "index")?,
|
||||
score: result.score,
|
||||
source_name: result.source_name,
|
||||
source_description: result.source_description,
|
||||
searchable_text: result.searchable_text,
|
||||
tools: serialize_tool_specs(result.tools)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_tool_specs(
|
||||
tools: Vec<codex_tools::LoadableToolSpec>,
|
||||
) -> Result<Vec<serde_json::Value>, JSONRPCErrorError> {
|
||||
tools
|
||||
.into_iter()
|
||||
.map(|tool| {
|
||||
serde_json::to_value(tool).map_err(|err| {
|
||||
internal_error(format!("failed to serialize tool_search tool: {err}"))
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn usize_to_u32(value: usize, field_name: &str) -> Result<u32, JSONRPCErrorError> {
|
||||
u32::try_from(value).map_err(|err| {
|
||||
internal_error(format!(
|
||||
"tool_search {field_name} value {value} does not fit in u32: {err}"
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
fn with_mcp_tool_call_thread_id_meta(
|
||||
meta: Option<serde_json::Value>,
|
||||
thread_id: &str,
|
||||
|
||||
Reference in New Issue
Block a user