mirror of
https://github.com/openai/codex.git
synced 2026-04-26 07:35:29 +00:00
[apps] Improve search tool fallback. (#14732)
- [x] Bypass tool search and stuff tool specs directly into model context when either a. Tool search is not available for the model or b. There are not that many tools to search for.
This commit is contained in:
@@ -18,6 +18,7 @@ const CONNECTOR_DESCRIPTION: &str = "Plan events and manage your calendar.";
|
||||
const PROTOCOL_VERSION: &str = "2025-11-25";
|
||||
const SERVER_NAME: &str = "codex-apps-test";
|
||||
const SERVER_VERSION: &str = "1.0.0";
|
||||
const SEARCHABLE_TOOL_COUNT: usize = 100;
|
||||
pub const CALENDAR_CREATE_EVENT_RESOURCE_URI: &str =
|
||||
"connector://calendar/tools/calendar_create_event";
|
||||
const CALENDAR_LIST_EVENTS_RESOURCE_URI: &str = "connector://calendar/tools/calendar_list_events";
|
||||
@@ -32,6 +33,21 @@ impl AppsTestServer {
|
||||
Self::mount_with_connector_name(server, CONNECTOR_NAME).await
|
||||
}
|
||||
|
||||
pub async fn mount_searchable(server: &MockServer) -> Result<Self> {
|
||||
mount_oauth_metadata(server).await;
|
||||
mount_connectors_directory(server).await;
|
||||
mount_streamable_http_json_rpc(
|
||||
server,
|
||||
CONNECTOR_NAME.to_string(),
|
||||
CONNECTOR_DESCRIPTION.to_string(),
|
||||
/*searchable*/ true,
|
||||
)
|
||||
.await;
|
||||
Ok(Self {
|
||||
chatgpt_base_url: server.uri(),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn mount_with_connector_name(
|
||||
server: &MockServer,
|
||||
connector_name: &str,
|
||||
@@ -42,6 +58,7 @@ impl AppsTestServer {
|
||||
server,
|
||||
connector_name.to_string(),
|
||||
CONNECTOR_DESCRIPTION.to_string(),
|
||||
/*searchable*/ false,
|
||||
)
|
||||
.await;
|
||||
Ok(Self {
|
||||
@@ -97,12 +114,14 @@ async fn mount_streamable_http_json_rpc(
|
||||
server: &MockServer,
|
||||
connector_name: String,
|
||||
connector_description: String,
|
||||
searchable: bool,
|
||||
) {
|
||||
Mock::given(method("POST"))
|
||||
.and(path_regex("^/api/codex/apps/?$"))
|
||||
.respond_with(CodexAppsJsonRpcResponder {
|
||||
connector_name,
|
||||
connector_description,
|
||||
searchable,
|
||||
})
|
||||
.mount(server)
|
||||
.await;
|
||||
@@ -111,6 +130,7 @@ async fn mount_streamable_http_json_rpc(
|
||||
struct CodexAppsJsonRpcResponder {
|
||||
connector_name: String,
|
||||
connector_description: String,
|
||||
searchable: bool,
|
||||
}
|
||||
|
||||
impl Respond for CodexAppsJsonRpcResponder {
|
||||
@@ -157,7 +177,7 @@ impl Respond for CodexAppsJsonRpcResponder {
|
||||
"notifications/initialized" => ResponseTemplate::new(202),
|
||||
"tools/list" => {
|
||||
let id = body.get("id").cloned().unwrap_or(Value::Null);
|
||||
ResponseTemplate::new(200).set_body_json(json!({
|
||||
let mut response = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"id": id,
|
||||
"result": {
|
||||
@@ -211,7 +231,32 @@ impl Respond for CodexAppsJsonRpcResponder {
|
||||
],
|
||||
"nextCursor": null
|
||||
}
|
||||
}))
|
||||
});
|
||||
if self.searchable
|
||||
&& let Some(tools) = response
|
||||
.pointer_mut("/result/tools")
|
||||
.and_then(Value::as_array_mut)
|
||||
{
|
||||
for index in 2..SEARCHABLE_TOOL_COUNT {
|
||||
tools.push(json!({
|
||||
"name": format!("calendar_timezone_option_{index}"),
|
||||
"description": format!("Read timezone option {index}."),
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"timezone": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"_meta": {
|
||||
"connector_id": CONNECTOR_ID,
|
||||
"connector_name": self.connector_name.clone(),
|
||||
"connector_description": self.connector_description.clone()
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
ResponseTemplate::new(200).set_body_json(response)
|
||||
}
|
||||
"tools/call" => {
|
||||
let id = body.get("id").cloned().unwrap_or(Value::Null);
|
||||
|
||||
Reference in New Issue
Block a user