mirror of
https://github.com/openai/codex.git
synced 2026-11-11 06:31:37 +00:00
## Why Selected plugin MCP servers may be skipped after the optional startup grace period. When a user explicitly mentions a plugin or MCP server, the turn should continue waiting so the requested tools are available to the model. ## What changed - Track explicitly mentioned plugin IDs and MCP servers across later samples, steered input, and same-turn restarts. - Require matching selected-plugin MCP servers to finish startup before capturing the tool catalog, while leaving unmentioned servers optional. - Match `plugin://` identities independently of display names and ignore targeting query parameters such as `app` and `browserFamily`. ## Testing Added coverage for linked and structured plugin mentions, direct and batched capability discovery, delayed environment attachment, steering, and same-turn restarts. GitOrigin-RevId: c509ef8df45df1a7edb0da6afdb2682dc53a4de8
106 lines
2.5 KiB
Rust
106 lines
2.5 KiB
Rust
use std::collections::HashSet;
|
|
|
|
use pretty_assertions::assert_eq;
|
|
|
|
use super::*;
|
|
|
|
fn set<'a>(items: &'a [&'a str]) -> HashSet<&'a str> {
|
|
items.iter().copied().collect()
|
|
}
|
|
|
|
fn assert_mentions(text: &str, expected_names: &[&str], expected_paths: &[&str]) {
|
|
let mentions = extract_tool_mentions(text);
|
|
assert_eq!(mentions.names, set(expected_names));
|
|
assert_eq!(mentions.paths, set(expected_paths));
|
|
}
|
|
|
|
#[test]
|
|
fn handles_plain_and_linked_mentions() {
|
|
assert_mentions(
|
|
"use $alpha and [$beta](/tmp/beta)",
|
|
&["alpha", "beta"],
|
|
&["/tmp/beta"],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn skips_common_env_vars() {
|
|
assert_mentions("use $PATH and $alpha", &["alpha"], &[]);
|
|
assert_mentions("use [$HOME](/tmp/skill)", &[], &[]);
|
|
assert_mentions("use $XDG_CONFIG_HOME and $beta", &["beta"], &[]);
|
|
}
|
|
|
|
#[test]
|
|
fn requires_link_syntax() {
|
|
assert_mentions("[beta](/tmp/beta)", &[], &[]);
|
|
assert_mentions("[$beta] /tmp/beta", &["beta"], &[]);
|
|
assert_mentions("[$beta]()", &["beta"], &[]);
|
|
}
|
|
|
|
#[test]
|
|
fn trims_linked_paths_and_allows_spacing() {
|
|
assert_mentions("use [$beta] ( /tmp/beta )", &["beta"], &["/tmp/beta"]);
|
|
}
|
|
|
|
#[test]
|
|
fn stops_at_non_name_chars() {
|
|
assert_mentions(
|
|
"use $alpha.skill and $beta_extra",
|
|
&["alpha", "beta_extra"],
|
|
&[],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn keeps_plugin_skill_namespaces() {
|
|
assert_mentions(
|
|
"use $slack:search and $alpha",
|
|
&["alpha", "slack:search"],
|
|
&[],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn requires_exact_name_boundaries() {
|
|
assert_mentions(
|
|
"use $notion-research-doc but not $notion-research-docs or $notion-research-doc_extra",
|
|
&[
|
|
"notion-research-doc",
|
|
"notion-research-docs",
|
|
"notion-research-doc_extra",
|
|
],
|
|
&[],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn handles_many_sigils_without_looping() {
|
|
let prefix = "$".repeat(256);
|
|
assert_mentions(&format!("{prefix} not-a-mention"), &[], &[]);
|
|
}
|
|
|
|
#[test]
|
|
fn plugin_config_names_ignore_mention_query_parameters() {
|
|
let paths = [
|
|
"plugin://sample@test",
|
|
"plugin://sample@test?app=com.example.editor",
|
|
"plugin://sample@test?browserFamily=chrome",
|
|
];
|
|
|
|
assert_eq!(
|
|
paths.map(plugin_config_name_from_path),
|
|
[Some("sample@test"); 3],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn plugin_config_names_require_a_plugin_identity() {
|
|
let paths = [
|
|
"plugin://",
|
|
"plugin://?app=com.example.editor",
|
|
"app://sample@test?app=com.example.editor",
|
|
];
|
|
|
|
assert_eq!(paths.map(plugin_config_name_from_path), [None; 3]);
|
|
}
|