mirror of
https://github.com/openai/codex.git
synced 2026-11-09 20:50:33 +00:00
Remove singular plugin install tool
This commit is contained in:
@@ -7,7 +7,6 @@ mod function_call_error;
|
||||
mod image_detail;
|
||||
mod json_schema;
|
||||
mod mcp_tool;
|
||||
mod request_plugin_install;
|
||||
mod response_history;
|
||||
mod responses_api;
|
||||
mod tool_call;
|
||||
@@ -39,15 +38,6 @@ pub use json_schema::parse_tool_input_schema;
|
||||
pub use json_schema::parse_tool_input_schema_without_compaction;
|
||||
pub use mcp_tool::mcp_call_tool_result_output_schema;
|
||||
pub use mcp_tool::parse_mcp_tool;
|
||||
pub use request_plugin_install::REQUEST_PLUGIN_INSTALL_APPROVAL_KIND_VALUE;
|
||||
pub use request_plugin_install::REQUEST_PLUGIN_INSTALL_PERSIST_ALWAYS_VALUE;
|
||||
pub use request_plugin_install::REQUEST_PLUGIN_INSTALL_PERSIST_KEY;
|
||||
pub use request_plugin_install::RequestPluginInstallArgs;
|
||||
pub use request_plugin_install::RequestPluginInstallMeta;
|
||||
pub use request_plugin_install::RequestPluginInstallResult;
|
||||
pub use request_plugin_install::all_requested_connectors_picked_up;
|
||||
pub use request_plugin_install::build_request_plugin_install_elicitation_request;
|
||||
pub use request_plugin_install::verified_connector_install_completed;
|
||||
pub use response_history::retain_tail_from_last_n_user_messages;
|
||||
pub use response_history::truncate_assistant_output_text_to_token_budget;
|
||||
pub use responses_api::FreeformTool;
|
||||
@@ -86,7 +76,6 @@ pub use tool_discovery::DiscoverableToolAction;
|
||||
pub use tool_discovery::DiscoverableToolType;
|
||||
pub use tool_discovery::LIST_AVAILABLE_PLUGINS_TO_INSTALL_TOOL_NAME;
|
||||
pub use tool_discovery::ListAvailablePluginsToInstallResult;
|
||||
pub use tool_discovery::REQUEST_PLUGIN_INSTALL_TOOL_NAME;
|
||||
pub use tool_discovery::RequestPluginInstallEntry;
|
||||
pub use tool_discovery::TOOL_SEARCH_DEFAULT_LIMIT;
|
||||
pub use tool_discovery::TOOL_SEARCH_TOOL_NAME;
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use codex_app_server_protocol::AppInfo;
|
||||
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 serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::DiscoverableTool;
|
||||
use crate::DiscoverableToolAction;
|
||||
use crate::DiscoverableToolType;
|
||||
|
||||
pub const REQUEST_PLUGIN_INSTALL_APPROVAL_KIND_VALUE: &str = "tool_suggestion";
|
||||
pub const REQUEST_PLUGIN_INSTALL_PERSIST_KEY: &str = "persist";
|
||||
pub const REQUEST_PLUGIN_INSTALL_PERSIST_ALWAYS_VALUE: &str = "always";
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct RequestPluginInstallArgs {
|
||||
pub tool_type: DiscoverableToolType,
|
||||
pub action_type: DiscoverableToolAction,
|
||||
pub tool_id: String,
|
||||
pub suggest_reason: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, PartialEq, Eq)]
|
||||
pub struct RequestPluginInstallResult {
|
||||
pub completed: bool,
|
||||
pub user_confirmed: bool,
|
||||
pub tool_type: DiscoverableToolType,
|
||||
pub action_type: DiscoverableToolAction,
|
||||
pub tool_id: String,
|
||||
pub tool_name: String,
|
||||
pub suggest_reason: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, PartialEq, Eq)]
|
||||
pub struct RequestPluginInstallMeta<'a> {
|
||||
pub codex_approval_kind: &'static str,
|
||||
pub persist: &'static str,
|
||||
pub tool_type: DiscoverableToolType,
|
||||
pub suggest_type: DiscoverableToolAction,
|
||||
pub suggest_reason: &'a str,
|
||||
pub tool_id: &'a str,
|
||||
pub tool_name: &'a str,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub install_url: Option<&'a str>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub remote_plugin_id: Option<&'a str>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub app_connector_ids: Option<&'a [String]>,
|
||||
}
|
||||
|
||||
pub fn build_request_plugin_install_elicitation_request(
|
||||
server_name: &str,
|
||||
thread_id: String,
|
||||
turn_id: String,
|
||||
suggest_reason: &str,
|
||||
tool: &DiscoverableTool,
|
||||
) -> McpServerElicitationRequestParams {
|
||||
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,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_requested_connectors_picked_up(
|
||||
expected_connector_ids: &[String],
|
||||
accessible_connectors: &[AppInfo],
|
||||
) -> bool {
|
||||
expected_connector_ids.iter().all(|connector_id| {
|
||||
verified_connector_install_completed(connector_id, accessible_connectors)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn verified_connector_install_completed(
|
||||
tool_id: &str,
|
||||
accessible_connectors: &[AppInfo],
|
||||
) -> bool {
|
||||
accessible_connectors
|
||||
.iter()
|
||||
.find(|connector| connector.id == tool_id)
|
||||
.is_some_and(|connector| connector.is_accessible)
|
||||
}
|
||||
|
||||
fn build_request_plugin_install_meta<'a>(
|
||||
suggest_reason: &'a str,
|
||||
tool: &'a DiscoverableTool,
|
||||
) -> RequestPluginInstallMeta<'a> {
|
||||
let (tool_type, remote_plugin_id, app_connector_ids) = match tool {
|
||||
DiscoverableTool::Connector(_) => (DiscoverableToolType::Connector, None, None),
|
||||
DiscoverableTool::Plugin(plugin) => (
|
||||
DiscoverableToolType::Plugin,
|
||||
plugin.remote_plugin_id.as_deref(),
|
||||
Some(plugin.app_connector_ids.as_slice()),
|
||||
),
|
||||
};
|
||||
RequestPluginInstallMeta {
|
||||
codex_approval_kind: REQUEST_PLUGIN_INSTALL_APPROVAL_KIND_VALUE,
|
||||
persist: REQUEST_PLUGIN_INSTALL_PERSIST_ALWAYS_VALUE,
|
||||
tool_type,
|
||||
suggest_type: DiscoverableToolAction::Install,
|
||||
suggest_reason,
|
||||
tool_id: tool.id(),
|
||||
tool_name: tool.name(),
|
||||
install_url: tool.install_url(),
|
||||
remote_plugin_id,
|
||||
app_connector_ids,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "request_plugin_install_tests.rs"]
|
||||
mod tests;
|
||||
@@ -1,214 +0,0 @@
|
||||
use super::*;
|
||||
use crate::DiscoverablePluginInfo;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn build_request_plugin_install_elicitation_request_uses_expected_shape() {
|
||||
let connector = DiscoverableTool::Connector(Box::new(AppInfo {
|
||||
id: "connector_2128aebfecb84f64a069897515042a44".to_string(),
|
||||
name: "Google Calendar".to_string(),
|
||||
description: Some("Plan events and schedules.".to_string()),
|
||||
logo_url: None,
|
||||
logo_url_dark: None,
|
||||
distribution_channel: None,
|
||||
branding: None,
|
||||
app_metadata: None,
|
||||
labels: None,
|
||||
install_url: Some(
|
||||
"https://chatgpt.com/apps/google-calendar/connector_2128aebfecb84f64a069897515042a44"
|
||||
.to_string(),
|
||||
),
|
||||
is_accessible: false,
|
||||
is_enabled: true,
|
||||
plugin_display_names: Vec::new(),
|
||||
}));
|
||||
|
||||
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,
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_request_plugin_install_elicitation_request_injects_plugin_metadata() {
|
||||
let plugin = DiscoverableTool::Plugin(Box::new(DiscoverablePluginInfo {
|
||||
id: "sample@openai-curated-remote".to_string(),
|
||||
remote_plugin_id: Some("plugins~Plugin_sample".to_string()),
|
||||
name: "Sample Plugin".to_string(),
|
||||
description: Some("Includes skills, MCP servers, and apps.".to_string()),
|
||||
has_skills: true,
|
||||
mcp_server_names: vec!["sample-docs".to_string()],
|
||||
app_connector_ids: vec!["connector_calendar".to_string()],
|
||||
}));
|
||||
|
||||
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,
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_request_plugin_install_meta_uses_expected_shape() {
|
||||
let connector = DiscoverableTool::Connector(Box::new(AppInfo {
|
||||
id: "connector_68df038e0ba48191908c8434991bbac2".to_string(),
|
||||
name: "Gmail".to_string(),
|
||||
description: None,
|
||||
logo_url: None,
|
||||
logo_url_dark: None,
|
||||
distribution_channel: None,
|
||||
branding: None,
|
||||
app_metadata: None,
|
||||
labels: None,
|
||||
install_url: Some(
|
||||
"https://chatgpt.com/apps/gmail/connector_68df038e0ba48191908c8434991bbac2".to_string(),
|
||||
),
|
||||
is_accessible: false,
|
||||
is_enabled: true,
|
||||
plugin_display_names: Vec::new(),
|
||||
}));
|
||||
let meta =
|
||||
build_request_plugin_install_meta("Find and reference emails from your inbox", &connector);
|
||||
|
||||
assert_eq!(
|
||||
meta,
|
||||
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: "Find and reference emails from your inbox",
|
||||
tool_id: "connector_68df038e0ba48191908c8434991bbac2",
|
||||
tool_name: "Gmail",
|
||||
install_url: Some(
|
||||
"https://chatgpt.com/apps/gmail/connector_68df038e0ba48191908c8434991bbac2"
|
||||
),
|
||||
remote_plugin_id: None,
|
||||
app_connector_ids: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verified_connector_install_completed_requires_accessible_connector() {
|
||||
let accessible_connectors = vec![AppInfo {
|
||||
id: "calendar".to_string(),
|
||||
name: "Google Calendar".to_string(),
|
||||
description: None,
|
||||
logo_url: None,
|
||||
logo_url_dark: None,
|
||||
distribution_channel: None,
|
||||
branding: None,
|
||||
app_metadata: None,
|
||||
labels: None,
|
||||
install_url: None,
|
||||
is_accessible: true,
|
||||
is_enabled: false,
|
||||
plugin_display_names: Vec::new(),
|
||||
}];
|
||||
|
||||
assert!(verified_connector_install_completed(
|
||||
"calendar",
|
||||
&accessible_connectors,
|
||||
));
|
||||
assert!(!verified_connector_install_completed(
|
||||
"gmail",
|
||||
&accessible_connectors,
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_requested_connectors_picked_up_requires_every_expected_connector() {
|
||||
let accessible_connectors = vec![AppInfo {
|
||||
id: "calendar".to_string(),
|
||||
name: "Google Calendar".to_string(),
|
||||
description: None,
|
||||
logo_url: None,
|
||||
logo_url_dark: None,
|
||||
distribution_channel: None,
|
||||
branding: None,
|
||||
app_metadata: None,
|
||||
labels: None,
|
||||
install_url: None,
|
||||
is_accessible: true,
|
||||
is_enabled: false,
|
||||
plugin_display_names: Vec::new(),
|
||||
}];
|
||||
|
||||
assert!(all_requested_connectors_picked_up(
|
||||
&["calendar".to_string()],
|
||||
&accessible_connectors,
|
||||
));
|
||||
assert!(!all_requested_connectors_picked_up(
|
||||
&["calendar".to_string(), "gmail".to_string()],
|
||||
&accessible_connectors,
|
||||
));
|
||||
}
|
||||
@@ -6,7 +6,6 @@ const TUI_CLIENT_NAME: &str = "codex-tui";
|
||||
pub const TOOL_SEARCH_TOOL_NAME: &str = "tool_search";
|
||||
pub const TOOL_SEARCH_DEFAULT_LIMIT: usize = 8;
|
||||
pub const LIST_AVAILABLE_PLUGINS_TO_INSTALL_TOOL_NAME: &str = "list_available_plugins_to_install";
|
||||
pub const REQUEST_PLUGIN_INSTALL_TOOL_NAME: &str = "request_plugin_install";
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ToolSearchSourceInfo {
|
||||
|
||||
Reference in New Issue
Block a user