[codex] [2/4] Generalize plugin suggestion presentation (#28400)

Summary
- Add list-backed and developer-context presentations for plugin
suggestion candidates.
- Let tool planning, install validation, and request-tool copy follow
the selected presentation.
- Keep every production caller on the existing list-backed presentation,
preserving the current list tool, request schema, connector behavior,
and model-visible copy.
- Leave developer-context presentation latent until the final PR in the
stack.

Stack
- 2/3, based on #28399.
- Follow-up: #27704 activates endpoint recommendations.

Validation
- `just test -p codex-core request_plugin_install`
- `just test -p codex-core spec_plan`
- `just fix -p codex-core`
- `just fmt`
- `git diff --check`
This commit is contained in:
Alex Daley
2026-06-16 18:44:10 -04:00
committed by GitHub
Unverified
parent 7e735b59ce
commit 587487df9e
9 changed files with 147 additions and 79 deletions
+2 -2
View File
@@ -571,9 +571,9 @@ fn test_tool_runtime(session: Arc<Session>, turn_context: Arc<TurnContext>) -> T
let router = Arc::new(ToolRouter::from_turn_context(
&turn_context,
crate::tools::router::ToolRouterParams {
tool_suggest_candidates: None,
mcp_tools: None,
deferred_mcp_tools: None,
discoverable_tools: None,
extension_tool_executors: Vec::new(),
dynamic_tools: turn_context.dynamic_tools.as_slice(),
},
@@ -9600,9 +9600,9 @@ async fn fatal_tool_error_stops_turn_and_reports_error() {
let router = ToolRouter::from_turn_context(
&turn_context,
crate::tools::router::ToolRouterParams {
tool_suggest_candidates: None,
deferred_mcp_tools,
mcp_tools: Some(tools),
discoverable_tools: None,
extension_tool_executors: Vec::new(),
dynamic_tools: turn_context.dynamic_tools.as_slice(),
},
+8 -3
View File
@@ -58,6 +58,8 @@ use crate::tools::context::SharedTurnDiffTracker;
use crate::tools::parallel::ToolCallRuntime;
use crate::tools::registry::ToolArgumentDiffConsumer;
use crate::tools::router::ToolRouterParams;
use crate::tools::router::ToolSuggestCandidates;
use crate::tools::router::ToolSuggestPresentation;
use crate::tools::router::extension_tool_executors;
use crate::tools::spec_plan::search_tool_enabled;
use crate::tools::spec_plan::tool_suggest_enabled;
@@ -1190,7 +1192,7 @@ pub(crate) async fn built_tools(
.into_iter()
.map(|connector_id| connector_id.0)
.collect::<Vec<_>>();
let discoverable_tools = async {
let tool_suggest_candidates = async {
if apps_enabled && tool_suggest_enabled(turn_context) {
if let Some(accessible_connectors) = accessible_connectors_with_enabled_state.as_ref() {
match connectors::list_tool_suggest_discoverable_tools_with_auth(
@@ -1208,7 +1210,10 @@ pub(crate) async fn built_tools(
)
}) {
Ok(discoverable_tools) if discoverable_tools.is_empty() => None,
Ok(discoverable_tools) => Some(discoverable_tools),
Ok(discoverable_tools) => Some(ToolSuggestCandidates {
tools: discoverable_tools,
presentation: ToolSuggestPresentation::ListTool,
}),
Err(err) => {
warn!("failed to load discoverable tool suggestions: {err:#}");
None
@@ -1237,7 +1242,7 @@ pub(crate) async fn built_tools(
ToolRouterParams {
mcp_tools,
deferred_mcp_tools,
discoverable_tools,
tool_suggest_candidates,
extension_tool_executors: extension_tool_executors(sess),
dynamic_tools: turn_context.dynamic_tools.as_slice(),
},