mirror of
https://github.com/openai/codex.git
synced 2026-05-17 17:53:06 +00:00
## Note-- added plugin mentions via @, but that conflicts with file mentions depends and builds upon #13433. - introduces explicit `@plugin` mentions. this injects the plugin's mcp servers, app names, and skill name format into turn context as a dev message. - we do not yet have UI for these mentions, so we currently parse raw text (as opposed to skills and apps which have UI chips, autocomplete, etc.) this depends on a `plugins/list` app-server endpoint we can feed the UI with, which is upcoming - also annotate mcp and app tool descriptions with the plugin(s) they come from. this gives the model a first class way of understanding what tools come from which plugins, which will help implicit invocation. ### Tests Added and updated tests, unit and integration. Also confirmed locally a raw `@plugin` injects the dev message, and the model knows about its apps, mcps, and skills.
91 lines
2.9 KiB
Rust
91 lines
2.9 KiB
Rust
use crate::plugins::PluginCapabilitySummary;
|
|
|
|
pub(crate) fn render_plugins_section(plugins: &[PluginCapabilitySummary]) -> Option<String> {
|
|
if plugins.is_empty() {
|
|
return None;
|
|
}
|
|
|
|
let mut lines = vec![
|
|
"## Plugins".to_string(),
|
|
"A plugin is a local bundle of skills, MCP servers, and apps. Below is the list of plugins that are enabled and available in this session.".to_string(),
|
|
"### Available plugins".to_string(),
|
|
];
|
|
|
|
lines.extend(
|
|
plugins
|
|
.iter()
|
|
.map(|plugin| format!("- `{}`", plugin.display_name)),
|
|
);
|
|
|
|
lines.push("### How to use plugins".to_string());
|
|
lines.push(
|
|
r###"- Discovery: The list above is the plugins available in this session.
|
|
- Trigger rules: If the user explicitly names a plugin, prefer capabilities associated with that plugin for that turn.
|
|
- Relationship to capabilities: Plugins are not invoked directly. Use their underlying skills, MCP tools, and app tools to help solve the task.
|
|
- Preference: When a relevant plugin is available, prefer using capabilities associated with that plugin over standalone capabilities that provide similar functionality.
|
|
- Missing/blocked: If the user requests a plugin that is not listed above, or the plugin does not have relevant callable capabilities for the task, say so briefly and continue with the best fallback."###
|
|
.to_string(),
|
|
);
|
|
|
|
Some(lines.join("\n"))
|
|
}
|
|
|
|
pub(crate) fn render_explicit_plugin_instructions(
|
|
plugin: &PluginCapabilitySummary,
|
|
available_mcp_servers: &[String],
|
|
available_apps: &[String],
|
|
) -> Option<String> {
|
|
let mut lines = vec![format!(
|
|
"Capabilities from the `{}` plugin:",
|
|
plugin.display_name
|
|
)];
|
|
|
|
if plugin.has_skills {
|
|
lines.push(format!(
|
|
"- Skills from this plugin are prefixed with `{}:`.",
|
|
plugin.display_name
|
|
));
|
|
}
|
|
|
|
if !available_mcp_servers.is_empty() {
|
|
lines.push(format!(
|
|
"- MCP servers from this plugin available in this session: {}.",
|
|
available_mcp_servers
|
|
.iter()
|
|
.map(|server| format!("`{server}`"))
|
|
.collect::<Vec<_>>()
|
|
.join(", ")
|
|
));
|
|
}
|
|
|
|
if !available_apps.is_empty() {
|
|
lines.push(format!(
|
|
"- Apps from this plugin available in this session: {}.",
|
|
available_apps
|
|
.iter()
|
|
.map(|app| format!("`{app}`"))
|
|
.collect::<Vec<_>>()
|
|
.join(", ")
|
|
));
|
|
}
|
|
|
|
if lines.len() == 1 {
|
|
return None;
|
|
}
|
|
|
|
lines.push("Use these plugin-associated capabilities to help solve the task.".to_string());
|
|
|
|
Some(lines.join("\n"))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
#[test]
|
|
fn render_plugins_section_returns_none_for_empty_plugins() {
|
|
assert_eq!(render_plugins_section(&[]), None);
|
|
}
|
|
}
|