mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
mcp: keep elicitation requests below app wire types (#29724)
## Why Core and tools need to request MCP elicitation without constructing app-server wire payloads. The request should remain a neutral protocol concept until app-server serializes it for a client. ## What changed - Switched core and tools to `codex_protocol::approvals::ElicitationRequest`. - Derived turn and server context inside core instead of carrying app-server request types through lower layers. - Kept the app-server payload unchanged through an explicit boundary conversion. - Removed the remaining production app-server-protocol dependency from tools. ## Stack This is PR 5 of 6, stacked on [PR #29723](https://github.com/openai/codex/pull/29723). Review only the delta from `codex/split-connector-metadata-types`. Next: [PR #29725](https://github.com/openai/codex/pull/29725). ## Validation - `codex-core` MCP coverage passed: 87 tests. - Tools elicitation and app-server round-trip coverage passed.
This commit is contained in:
committed by
GitHub
Unverified
parent
a33ad93996
commit
df1ee09ec5
Generated
-1
@@ -4020,7 +4020,6 @@ dependencies = [
|
||||
name = "codex-tools"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"codex-app-server-protocol",
|
||||
"codex-code-mode",
|
||||
"codex-connectors",
|
||||
"codex-features",
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
use std::time::Instant;
|
||||
@@ -26,10 +25,6 @@ use crate::turn_metadata::McpTurnMetadataContext;
|
||||
use codex_analytics::AppInvocation;
|
||||
use codex_analytics::InvocationType;
|
||||
use codex_analytics::build_track_events_context;
|
||||
use codex_app_server_protocol::McpElicitationObjectType;
|
||||
use codex_app_server_protocol::McpElicitationSchema;
|
||||
use codex_app_server_protocol::McpServerElicitationRequest;
|
||||
use codex_app_server_protocol::McpServerElicitationRequestParams;
|
||||
use codex_config::ConfigLayerSource;
|
||||
use codex_config::types::AppToolApproval;
|
||||
use codex_config::types::ApprovalsReviewer;
|
||||
@@ -46,6 +41,7 @@ use codex_mcp::auth_elicitation_completed_result;
|
||||
use codex_mcp::build_auth_elicitation_plan;
|
||||
use codex_mcp::declared_openai_file_input_param_names;
|
||||
use codex_mcp::mcp_permission_prompt_is_auto_approved;
|
||||
use codex_protocol::approvals::ElicitationRequest;
|
||||
use codex_protocol::items::McpToolCallError;
|
||||
use codex_protocol::items::McpToolCallItem;
|
||||
use codex_protocol::items::McpToolCallStatus;
|
||||
@@ -653,19 +649,19 @@ async fn maybe_request_codex_apps_auth_elicitation(
|
||||
};
|
||||
|
||||
let request_id = rmcp::model::RequestId::String(plan.elicitation.elicitation_id.clone().into());
|
||||
let params = McpServerElicitationRequestParams {
|
||||
thread_id: sess.thread_id.to_string(),
|
||||
turn_id: Some(turn_context.sub_id.clone()),
|
||||
server_name: CODEX_APPS_MCP_SERVER_NAME.to_string(),
|
||||
request: McpServerElicitationRequest::Url {
|
||||
meta: Some(plan.elicitation.meta),
|
||||
message: plan.elicitation.message,
|
||||
url: plan.elicitation.url,
|
||||
elicitation_id: plan.elicitation.elicitation_id,
|
||||
},
|
||||
let request = ElicitationRequest::Url {
|
||||
meta: Some(plan.elicitation.meta),
|
||||
message: plan.elicitation.message,
|
||||
url: plan.elicitation.url,
|
||||
elicitation_id: plan.elicitation.elicitation_id,
|
||||
};
|
||||
let response = sess
|
||||
.request_mcp_server_elicitation(turn_context, request_id, params)
|
||||
.request_mcp_server_elicitation(
|
||||
turn_context,
|
||||
CODEX_APPS_MCP_SERVER_NAME.to_string(),
|
||||
request_id,
|
||||
request,
|
||||
)
|
||||
.await
|
||||
.response;
|
||||
if !response
|
||||
@@ -1309,10 +1305,8 @@ async fn maybe_request_mcp_tool_approval(
|
||||
let request_id = rmcp::model::RequestId::String(
|
||||
format!("{MCP_TOOL_APPROVAL_QUESTION_ID_PREFIX}_{call_id}").into(),
|
||||
);
|
||||
let params = build_mcp_tool_approval_elicitation_request(
|
||||
sess.as_ref(),
|
||||
turn_context.as_ref(),
|
||||
McpToolApprovalElicitationRequest {
|
||||
let request =
|
||||
build_mcp_tool_approval_elicitation_request(McpToolApprovalElicitationRequest {
|
||||
server: &invocation.server,
|
||||
metadata,
|
||||
tool_params: rendered_template
|
||||
@@ -1325,12 +1319,16 @@ async fn maybe_request_mcp_tool_approval(
|
||||
.as_ref()
|
||||
.map(|rendered_template| rendered_template.elicitation_message.as_str()),
|
||||
prompt_options,
|
||||
},
|
||||
);
|
||||
});
|
||||
let decision = parse_mcp_tool_approval_elicitation_response(
|
||||
sess.request_mcp_server_elicitation(turn_context.as_ref(), request_id, params)
|
||||
.await
|
||||
.response,
|
||||
sess.request_mcp_server_elicitation(
|
||||
turn_context.as_ref(),
|
||||
invocation.server.clone(),
|
||||
request_id,
|
||||
request,
|
||||
)
|
||||
.await
|
||||
.response,
|
||||
&question_id,
|
||||
);
|
||||
let decision = normalize_approval_decision_for_mode(decision, approval_mode);
|
||||
@@ -1658,35 +1656,26 @@ fn build_mcp_tool_approval_fallback_message(
|
||||
}
|
||||
|
||||
fn build_mcp_tool_approval_elicitation_request(
|
||||
sess: &Session,
|
||||
turn_context: &TurnContext,
|
||||
request: McpToolApprovalElicitationRequest<'_>,
|
||||
) -> McpServerElicitationRequestParams {
|
||||
) -> ElicitationRequest {
|
||||
let message = request
|
||||
.message_override
|
||||
.map(ToString::to_string)
|
||||
.unwrap_or_else(|| request.question.question.clone());
|
||||
|
||||
McpServerElicitationRequestParams {
|
||||
thread_id: sess.thread_id.to_string(),
|
||||
turn_id: Some(turn_context.sub_id.clone()),
|
||||
server_name: request.server.to_string(),
|
||||
request: McpServerElicitationRequest::Form {
|
||||
meta: build_mcp_tool_approval_elicitation_meta(
|
||||
request.server,
|
||||
request.metadata,
|
||||
request.tool_params,
|
||||
request.tool_params_display,
|
||||
request.prompt_options,
|
||||
),
|
||||
message,
|
||||
requested_schema: McpElicitationSchema {
|
||||
schema_uri: None,
|
||||
type_: McpElicitationObjectType::Object,
|
||||
properties: BTreeMap::new(),
|
||||
required: None,
|
||||
},
|
||||
},
|
||||
ElicitationRequest::Form {
|
||||
meta: build_mcp_tool_approval_elicitation_meta(
|
||||
request.server,
|
||||
request.metadata,
|
||||
request.tool_params,
|
||||
request.tool_params_display,
|
||||
request.prompt_options,
|
||||
),
|
||||
message,
|
||||
requested_schema: serde_json::json!({
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -653,9 +653,8 @@ fn truncates_strings_on_char_boundaries() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn approval_elicitation_request_uses_message_override_and_preserves_tool_params_keys() {
|
||||
let (session, turn_context) = make_session_and_context().await;
|
||||
#[test]
|
||||
fn approval_elicitation_request_uses_message_override_and_preserves_tool_params_keys() {
|
||||
let question = build_mcp_tool_approval_question(
|
||||
"q".to_string(),
|
||||
CODEX_APPS_MCP_SERVER_NAME,
|
||||
@@ -667,86 +666,75 @@ async fn approval_elicitation_request_uses_message_override_and_preserves_tool_p
|
||||
Some("Allow Calendar to create an event?"),
|
||||
);
|
||||
|
||||
let request = build_mcp_tool_approval_elicitation_request(
|
||||
&session,
|
||||
&turn_context,
|
||||
McpToolApprovalElicitationRequest {
|
||||
server: CODEX_APPS_MCP_SERVER_NAME,
|
||||
metadata: Some(&approval_metadata(
|
||||
Some("calendar"),
|
||||
Some("Calendar"),
|
||||
Some("Manage events and schedules."),
|
||||
Some("Create Event"),
|
||||
Some("Create a calendar event."),
|
||||
)),
|
||||
tool_params: Some(&serde_json::json!({
|
||||
"calendar_id": "primary",
|
||||
"title": "Roadmap review",
|
||||
})),
|
||||
tool_params_display: Some(&[
|
||||
RenderedMcpToolApprovalParam {
|
||||
name: "calendar_id".to_string(),
|
||||
value: serde_json::json!("primary"),
|
||||
display_name: "Calendar".to_string(),
|
||||
},
|
||||
RenderedMcpToolApprovalParam {
|
||||
name: "title".to_string(),
|
||||
value: serde_json::json!("Roadmap review"),
|
||||
display_name: "Title".to_string(),
|
||||
},
|
||||
]),
|
||||
question,
|
||||
message_override: Some("Allow Calendar to create an event?"),
|
||||
prompt_options: prompt_options(
|
||||
/*allow_session_remember*/ true, /*allow_persistent_approval*/ true,
|
||||
),
|
||||
},
|
||||
);
|
||||
let request = build_mcp_tool_approval_elicitation_request(McpToolApprovalElicitationRequest {
|
||||
server: CODEX_APPS_MCP_SERVER_NAME,
|
||||
metadata: Some(&approval_metadata(
|
||||
Some("calendar"),
|
||||
Some("Calendar"),
|
||||
Some("Manage events and schedules."),
|
||||
Some("Create Event"),
|
||||
Some("Create a calendar event."),
|
||||
)),
|
||||
tool_params: Some(&serde_json::json!({
|
||||
"calendar_id": "primary",
|
||||
"title": "Roadmap review",
|
||||
})),
|
||||
tool_params_display: Some(&[
|
||||
RenderedMcpToolApprovalParam {
|
||||
name: "calendar_id".to_string(),
|
||||
value: serde_json::json!("primary"),
|
||||
display_name: "Calendar".to_string(),
|
||||
},
|
||||
RenderedMcpToolApprovalParam {
|
||||
name: "title".to_string(),
|
||||
value: serde_json::json!("Roadmap review"),
|
||||
display_name: "Title".to_string(),
|
||||
},
|
||||
]),
|
||||
question,
|
||||
message_override: Some("Allow Calendar to create an event?"),
|
||||
prompt_options: prompt_options(
|
||||
/*allow_session_remember*/ true, /*allow_persistent_approval*/ true,
|
||||
),
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
request,
|
||||
McpServerElicitationRequestParams {
|
||||
thread_id: session.thread_id.to_string(),
|
||||
turn_id: Some(turn_context.sub_id),
|
||||
server_name: CODEX_APPS_MCP_SERVER_NAME.to_string(),
|
||||
request: McpServerElicitationRequest::Form {
|
||||
meta: Some(serde_json::json!({
|
||||
MCP_TOOL_APPROVAL_KIND_KEY: MCP_TOOL_APPROVAL_KIND_MCP_TOOL_CALL,
|
||||
MCP_TOOL_APPROVAL_PERSIST_KEY: [
|
||||
MCP_TOOL_APPROVAL_PERSIST_SESSION,
|
||||
MCP_TOOL_APPROVAL_PERSIST_ALWAYS,
|
||||
],
|
||||
MCP_TOOL_APPROVAL_SOURCE_KEY: MCP_TOOL_APPROVAL_SOURCE_CONNECTOR,
|
||||
MCP_TOOL_APPROVAL_CONNECTOR_ID_KEY: "calendar",
|
||||
MCP_TOOL_APPROVAL_CONNECTOR_NAME_KEY: "Calendar",
|
||||
MCP_TOOL_APPROVAL_CONNECTOR_DESCRIPTION_KEY: "Manage events and schedules.",
|
||||
MCP_TOOL_APPROVAL_TOOL_TITLE_KEY: "Create Event",
|
||||
MCP_TOOL_APPROVAL_TOOL_DESCRIPTION_KEY: "Create a calendar event.",
|
||||
MCP_TOOL_APPROVAL_TOOL_PARAMS_KEY: {
|
||||
"calendar_id": "primary",
|
||||
"title": "Roadmap review",
|
||||
},
|
||||
MCP_TOOL_APPROVAL_TOOL_PARAMS_DISPLAY_KEY: [
|
||||
{
|
||||
"name": "calendar_id",
|
||||
"value": "primary",
|
||||
"display_name": "Calendar",
|
||||
},
|
||||
{
|
||||
"name": "title",
|
||||
"value": "Roadmap review",
|
||||
"display_name": "Title",
|
||||
},
|
||||
],
|
||||
})),
|
||||
message: "Allow Calendar to create an event?".to_string(),
|
||||
requested_schema: McpElicitationSchema {
|
||||
schema_uri: None,
|
||||
type_: McpElicitationObjectType::Object,
|
||||
properties: BTreeMap::new(),
|
||||
required: None,
|
||||
ElicitationRequest::Form {
|
||||
meta: Some(serde_json::json!({
|
||||
MCP_TOOL_APPROVAL_KIND_KEY: MCP_TOOL_APPROVAL_KIND_MCP_TOOL_CALL,
|
||||
MCP_TOOL_APPROVAL_PERSIST_KEY: [
|
||||
MCP_TOOL_APPROVAL_PERSIST_SESSION,
|
||||
MCP_TOOL_APPROVAL_PERSIST_ALWAYS,
|
||||
],
|
||||
MCP_TOOL_APPROVAL_SOURCE_KEY: MCP_TOOL_APPROVAL_SOURCE_CONNECTOR,
|
||||
MCP_TOOL_APPROVAL_CONNECTOR_ID_KEY: "calendar",
|
||||
MCP_TOOL_APPROVAL_CONNECTOR_NAME_KEY: "Calendar",
|
||||
MCP_TOOL_APPROVAL_CONNECTOR_DESCRIPTION_KEY: "Manage events and schedules.",
|
||||
MCP_TOOL_APPROVAL_TOOL_TITLE_KEY: "Create Event",
|
||||
MCP_TOOL_APPROVAL_TOOL_DESCRIPTION_KEY: "Create a calendar event.",
|
||||
MCP_TOOL_APPROVAL_TOOL_PARAMS_KEY: {
|
||||
"calendar_id": "primary",
|
||||
"title": "Roadmap review",
|
||||
},
|
||||
},
|
||||
MCP_TOOL_APPROVAL_TOOL_PARAMS_DISPLAY_KEY: [
|
||||
{
|
||||
"name": "calendar_id",
|
||||
"value": "primary",
|
||||
"display_name": "Calendar",
|
||||
},
|
||||
{
|
||||
"name": "title",
|
||||
"value": "Roadmap review",
|
||||
"display_name": "Title",
|
||||
},
|
||||
],
|
||||
})),
|
||||
message: "Allow Calendar to create an event?".to_string(),
|
||||
requested_schema: serde_json::json!({
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -99,8 +99,9 @@ impl Session {
|
||||
pub async fn request_mcp_server_elicitation(
|
||||
&self,
|
||||
turn_context: &TurnContext,
|
||||
server_name: String,
|
||||
request_id: RequestId,
|
||||
params: McpServerElicitationRequestParams,
|
||||
request: ElicitationRequest,
|
||||
) -> McpServerElicitationOutcome {
|
||||
if self
|
||||
.services
|
||||
@@ -118,53 +119,6 @@ impl Session {
|
||||
};
|
||||
}
|
||||
|
||||
let server_name = params.server_name.clone();
|
||||
let request = match params.request {
|
||||
McpServerElicitationRequest::Form {
|
||||
meta,
|
||||
message,
|
||||
requested_schema,
|
||||
} => {
|
||||
let requested_schema = match serde_json::to_value(requested_schema) {
|
||||
Ok(requested_schema) => requested_schema,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"failed to serialize MCP elicitation schema for server_name: {server_name}, request_id: {request_id}: {err:#}"
|
||||
);
|
||||
return McpServerElicitationOutcome {
|
||||
response: None,
|
||||
sent: false,
|
||||
};
|
||||
}
|
||||
};
|
||||
codex_protocol::approvals::ElicitationRequest::Form {
|
||||
meta,
|
||||
message,
|
||||
requested_schema,
|
||||
}
|
||||
}
|
||||
McpServerElicitationRequest::OpenAiForm {
|
||||
meta,
|
||||
message,
|
||||
requested_schema,
|
||||
} => codex_protocol::approvals::ElicitationRequest::OpenAiForm {
|
||||
meta,
|
||||
message,
|
||||
requested_schema,
|
||||
},
|
||||
McpServerElicitationRequest::Url {
|
||||
meta,
|
||||
message,
|
||||
url,
|
||||
elicitation_id,
|
||||
} => codex_protocol::approvals::ElicitationRequest::Url {
|
||||
meta,
|
||||
message,
|
||||
url,
|
||||
elicitation_id,
|
||||
},
|
||||
};
|
||||
|
||||
let (tx_response, rx_response) = oneshot::channel();
|
||||
let prev_entry = {
|
||||
let mut active = self.active_turn.lock().await;
|
||||
@@ -194,7 +148,7 @@ impl Session {
|
||||
}
|
||||
};
|
||||
let event = EventMsg::ElicitationRequest(ElicitationRequestEvent {
|
||||
turn_id: params.turn_id,
|
||||
turn_id: Some(turn_context.sub_id.clone()),
|
||||
server_name,
|
||||
id,
|
||||
request,
|
||||
|
||||
@@ -54,8 +54,6 @@ use chrono::Utc;
|
||||
use codex_analytics::AnalyticsEventsClient;
|
||||
use codex_analytics::SubAgentThreadStartedInput;
|
||||
use codex_analytics::TurnCodexErrorFact;
|
||||
use codex_app_server_protocol::McpServerElicitationRequest;
|
||||
use codex_app_server_protocol::McpServerElicitationRequestParams;
|
||||
use codex_config::types::AuthKeyringBackendKind;
|
||||
use codex_config::types::OAuthCredentialsStoreMode;
|
||||
use codex_exec_server::Environment;
|
||||
@@ -87,6 +85,7 @@ use codex_otel::current_span_w3c_trace_context;
|
||||
use codex_otel::set_parent_from_w3c_trace_context;
|
||||
use codex_protocol::SessionId;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::approvals::ElicitationRequest;
|
||||
use codex_protocol::approvals::ElicitationRequestEvent;
|
||||
use codex_protocol::approvals::ExecPolicyAmendment;
|
||||
use codex_protocol::approvals::NetworkPolicyAmendment;
|
||||
|
||||
@@ -84,7 +84,6 @@ use crate::tools::handlers::ShellCommandHandler;
|
||||
use crate::tools::registry::ToolExecutor;
|
||||
use crate::tools::router::ToolCallSource;
|
||||
use crate::turn_diff_tracker::TurnDiffTracker;
|
||||
use codex_app_server_protocol::McpElicitationSchema;
|
||||
use codex_config::config_toml::ConfigToml;
|
||||
use codex_config::config_toml::ProjectConfig;
|
||||
use codex_config::permissions_toml::FilesystemPermissionToml;
|
||||
@@ -377,24 +376,18 @@ async fn request_mcp_server_elicitation_auto_accepts_when_auto_deny_is_enabled()
|
||||
.load_full()
|
||||
.set_elicitations_auto_deny(/*auto_deny*/ true);
|
||||
|
||||
let requested_schema: McpElicitationSchema = serde_json::from_value(json!({
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
}))
|
||||
.expect("schema should deserialize");
|
||||
let response = session
|
||||
.request_mcp_server_elicitation(
|
||||
turn_context.as_ref(),
|
||||
"codex_apps".to_string(),
|
||||
RequestId::String("request-1".into()),
|
||||
McpServerElicitationRequestParams {
|
||||
thread_id: session.thread_id.to_string(),
|
||||
turn_id: Some(turn_context.sub_id.clone()),
|
||||
server_name: "codex_apps".to_string(),
|
||||
request: McpServerElicitationRequest::Form {
|
||||
meta: None,
|
||||
message: "Allow this request?".to_string(),
|
||||
requested_schema,
|
||||
},
|
||||
ElicitationRequest::Form {
|
||||
meta: None,
|
||||
message: "Allow this request?".to_string(),
|
||||
requested_schema: json!({
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
}),
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -173,15 +173,14 @@ impl RequestPluginInstallHandler {
|
||||
let tool_type = tool.tool_type();
|
||||
|
||||
let request_id = RequestId::String(format!("request_plugin_install_{call_id}").into());
|
||||
let params = build_request_plugin_install_elicitation_request(
|
||||
CODEX_APPS_MCP_SERVER_NAME,
|
||||
session.thread_id.to_string(),
|
||||
turn.sub_id.clone(),
|
||||
suggest_reason,
|
||||
&tool,
|
||||
);
|
||||
let request = build_request_plugin_install_elicitation_request(suggest_reason, &tool);
|
||||
let elicitation = session
|
||||
.request_mcp_server_elicitation(turn.as_ref(), request_id, params)
|
||||
.request_mcp_server_elicitation(
|
||||
turn.as_ref(),
|
||||
CODEX_APPS_MCP_SERVER_NAME.to_string(),
|
||||
request_id,
|
||||
request,
|
||||
)
|
||||
.await;
|
||||
let response = elicitation.response;
|
||||
if let Some(response) = response.as_ref() {
|
||||
|
||||
@@ -8,7 +8,6 @@ version.workspace = true
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
codex-app-server-protocol = { workspace = true }
|
||||
codex-code-mode = { workspace = true }
|
||||
codex-connectors = { workspace = true }
|
||||
codex-features = { workspace = true }
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use codex_app_server_protocol::McpElicitationObjectType;
|
||||
use codex_app_server_protocol::McpElicitationSchema;
|
||||
use codex_app_server_protocol::McpServerElicitationRequest;
|
||||
use codex_app_server_protocol::McpServerElicitationRequestParams;
|
||||
use codex_connectors::AppInfo;
|
||||
use codex_protocol::approvals::ElicitationRequest;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use serde_json::json;
|
||||
@@ -54,31 +49,21 @@ pub struct RequestPluginInstallMeta<'a> {
|
||||
}
|
||||
|
||||
pub fn build_request_plugin_install_elicitation_request(
|
||||
server_name: &str,
|
||||
thread_id: String,
|
||||
turn_id: String,
|
||||
suggest_reason: &str,
|
||||
tool: &DiscoverableTool,
|
||||
) -> McpServerElicitationRequestParams {
|
||||
) -> ElicitationRequest {
|
||||
let message = suggest_reason.to_string();
|
||||
|
||||
McpServerElicitationRequestParams {
|
||||
thread_id,
|
||||
turn_id: Some(turn_id),
|
||||
server_name: server_name.to_string(),
|
||||
request: McpServerElicitationRequest::Form {
|
||||
meta: Some(json!(build_request_plugin_install_meta(
|
||||
suggest_reason,
|
||||
tool,
|
||||
))),
|
||||
message,
|
||||
requested_schema: McpElicitationSchema {
|
||||
schema_uri: None,
|
||||
type_: McpElicitationObjectType::Object,
|
||||
properties: BTreeMap::new(),
|
||||
required: None,
|
||||
},
|
||||
},
|
||||
ElicitationRequest::Form {
|
||||
meta: Some(json!(build_request_plugin_install_meta(
|
||||
suggest_reason,
|
||||
tool,
|
||||
))),
|
||||
message,
|
||||
requested_schema: json!({
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,42 +27,32 @@ fn build_request_plugin_install_elicitation_request_uses_expected_shape() {
|
||||
}));
|
||||
|
||||
let request = build_request_plugin_install_elicitation_request(
|
||||
"codex-apps",
|
||||
"thread-1".to_string(),
|
||||
"turn-1".to_string(),
|
||||
"Plan and reference events from your calendar",
|
||||
&connector,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
request,
|
||||
McpServerElicitationRequestParams {
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn_id: Some("turn-1".to_string()),
|
||||
server_name: "codex-apps".to_string(),
|
||||
request: McpServerElicitationRequest::Form {
|
||||
meta: Some(json!(RequestPluginInstallMeta {
|
||||
codex_approval_kind: REQUEST_PLUGIN_INSTALL_APPROVAL_KIND_VALUE,
|
||||
persist: REQUEST_PLUGIN_INSTALL_PERSIST_ALWAYS_VALUE,
|
||||
tool_type: DiscoverableToolType::Connector,
|
||||
suggest_type: DiscoverableToolAction::Install,
|
||||
suggest_reason: "Plan and reference events from your calendar",
|
||||
tool_id: "connector_2128aebfecb84f64a069897515042a44",
|
||||
tool_name: "Google Calendar",
|
||||
install_url: Some(
|
||||
"https://chatgpt.com/apps/google-calendar/connector_2128aebfecb84f64a069897515042a44"
|
||||
),
|
||||
remote_plugin_id: None,
|
||||
app_connector_ids: None,
|
||||
})),
|
||||
message: "Plan and reference events from your calendar".to_string(),
|
||||
requested_schema: McpElicitationSchema {
|
||||
schema_uri: None,
|
||||
type_: McpElicitationObjectType::Object,
|
||||
properties: BTreeMap::new(),
|
||||
required: None,
|
||||
},
|
||||
},
|
||||
ElicitationRequest::Form {
|
||||
meta: Some(json!(RequestPluginInstallMeta {
|
||||
codex_approval_kind: REQUEST_PLUGIN_INSTALL_APPROVAL_KIND_VALUE,
|
||||
persist: REQUEST_PLUGIN_INSTALL_PERSIST_ALWAYS_VALUE,
|
||||
tool_type: DiscoverableToolType::Connector,
|
||||
suggest_type: DiscoverableToolAction::Install,
|
||||
suggest_reason: "Plan and reference events from your calendar",
|
||||
tool_id: "connector_2128aebfecb84f64a069897515042a44",
|
||||
tool_name: "Google Calendar",
|
||||
install_url: Some(
|
||||
"https://chatgpt.com/apps/google-calendar/connector_2128aebfecb84f64a069897515042a44"
|
||||
),
|
||||
remote_plugin_id: None,
|
||||
app_connector_ids: None,
|
||||
})),
|
||||
message: "Plan and reference events from your calendar".to_string(),
|
||||
requested_schema: json!({
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
}),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -80,40 +70,30 @@ fn build_request_plugin_install_elicitation_request_injects_plugin_metadata() {
|
||||
}));
|
||||
|
||||
let request = build_request_plugin_install_elicitation_request(
|
||||
"codex-apps",
|
||||
"thread-1".to_string(),
|
||||
"turn-1".to_string(),
|
||||
"Use the sample plugin's skills and MCP server",
|
||||
&plugin,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
request,
|
||||
McpServerElicitationRequestParams {
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn_id: Some("turn-1".to_string()),
|
||||
server_name: "codex-apps".to_string(),
|
||||
request: McpServerElicitationRequest::Form {
|
||||
meta: Some(json!(RequestPluginInstallMeta {
|
||||
codex_approval_kind: REQUEST_PLUGIN_INSTALL_APPROVAL_KIND_VALUE,
|
||||
persist: REQUEST_PLUGIN_INSTALL_PERSIST_ALWAYS_VALUE,
|
||||
tool_type: DiscoverableToolType::Plugin,
|
||||
suggest_type: DiscoverableToolAction::Install,
|
||||
suggest_reason: "Use the sample plugin's skills and MCP server",
|
||||
tool_id: "sample@openai-curated-remote",
|
||||
tool_name: "Sample Plugin",
|
||||
install_url: None,
|
||||
remote_plugin_id: Some("plugins~Plugin_sample"),
|
||||
app_connector_ids: Some(&["connector_calendar".to_string()]),
|
||||
})),
|
||||
message: "Use the sample plugin's skills and MCP server".to_string(),
|
||||
requested_schema: McpElicitationSchema {
|
||||
schema_uri: None,
|
||||
type_: McpElicitationObjectType::Object,
|
||||
properties: BTreeMap::new(),
|
||||
required: None,
|
||||
},
|
||||
},
|
||||
ElicitationRequest::Form {
|
||||
meta: Some(json!(RequestPluginInstallMeta {
|
||||
codex_approval_kind: REQUEST_PLUGIN_INSTALL_APPROVAL_KIND_VALUE,
|
||||
persist: REQUEST_PLUGIN_INSTALL_PERSIST_ALWAYS_VALUE,
|
||||
tool_type: DiscoverableToolType::Plugin,
|
||||
suggest_type: DiscoverableToolAction::Install,
|
||||
suggest_reason: "Use the sample plugin's skills and MCP server",
|
||||
tool_id: "sample@openai-curated-remote",
|
||||
tool_name: "Sample Plugin",
|
||||
install_url: None,
|
||||
remote_plugin_id: Some("plugins~Plugin_sample"),
|
||||
app_connector_ids: Some(&["connector_calendar".to_string()]),
|
||||
})),
|
||||
message: "Use the sample plugin's skills and MCP server".to_string(),
|
||||
requested_schema: json!({
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
}),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user