mirror of
https://github.com/openai/codex.git
synced 2026-10-19 17:28:46 +00:00
Detect implicit skill invocations from PowerShell reads (#38228)
## What changed - Recognize `Get-Content` reads of indexed `SKILL.md` files as implicit skill invocations. - Support the optional `-Raw` flag, quoted paths containing spaces, and Windows paths without stripping backslashes. ## Testing - Add unit coverage for the supported `Get-Content` forms and Windows path parsing. GitOrigin-RevId: 681f2e2fff9a597326bc94b97a31e311ef21b949
This commit is contained in:
@@ -35,6 +35,7 @@ pub fn detect_implicit_skill_invocation_for_command(
|
||||
}
|
||||
|
||||
detect_skill_doc_read(outcome, tokens.as_slice(), &workdir)
|
||||
.or_else(|| detect_powershell_skill_doc_read(outcome, command, &workdir))
|
||||
}
|
||||
|
||||
/// Resolves statically recognizable skill accesses without consulting the host filesystem.
|
||||
@@ -150,6 +151,44 @@ fn detect_skill_doc_read(
|
||||
None
|
||||
}
|
||||
|
||||
fn detect_powershell_skill_doc_read(
|
||||
outcome: &impl ImplicitSkillLookup,
|
||||
command: &str,
|
||||
workdir: &AbsolutePathBuf,
|
||||
) -> Option<SkillMetadata> {
|
||||
let path = powershell_get_content_path(command)?;
|
||||
let candidate_path = canonicalize_if_exists(&workdir.join(Path::new(path)));
|
||||
outcome
|
||||
.implicit_skill_for_doc_path(&candidate_path)
|
||||
.cloned()
|
||||
}
|
||||
|
||||
fn powershell_get_content_path(command: &str) -> Option<&str> {
|
||||
let mut arguments = command.trim().strip_prefix("Get-Content ")?;
|
||||
if let Some(remaining_arguments) = arguments.strip_prefix("-Raw ") {
|
||||
arguments = remaining_arguments;
|
||||
}
|
||||
|
||||
let (path, trailing) = if let Some(quoted_path) = arguments.strip_prefix('"') {
|
||||
let closing_quote = quoted_path.find('"')?;
|
||||
(
|
||||
"ed_path[..closing_quote],
|
||||
"ed_path[closing_quote + 1..],
|
||||
)
|
||||
} else {
|
||||
let path_end = arguments
|
||||
.char_indices()
|
||||
.find_map(|(index, character)| character.is_whitespace().then_some(index))
|
||||
.unwrap_or(arguments.len());
|
||||
(&arguments[..path_end], &arguments[path_end..])
|
||||
};
|
||||
|
||||
if path.is_empty() || path.starts_with('-') || !trailing.trim().is_empty() {
|
||||
return None;
|
||||
}
|
||||
Some(path)
|
||||
}
|
||||
|
||||
fn command_basename(command: &str) -> String {
|
||||
Path::new(command)
|
||||
.file_name()
|
||||
|
||||
@@ -64,6 +64,50 @@ fn script_run_detection_excludes_python_c() {
|
||||
assert!(script_run_token(&tokens).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn powershell_skill_doc_read_matches_common_forms() {
|
||||
let skill_doc_path = test_path_buf("/tmp/skill-test/SKILL.md").abs();
|
||||
let spaced_skill_doc_path = test_path_buf("/tmp/skill test/SKILL.md").abs();
|
||||
let skill = test_skill_metadata(skill_doc_path.clone());
|
||||
let spaced_skill = test_skill_metadata(spaced_skill_doc_path.clone());
|
||||
let outcome = TestLookup {
|
||||
by_doc_path: HashMap::from([
|
||||
(canonicalize_if_exists(&skill_doc_path), skill),
|
||||
(canonicalize_if_exists(&spaced_skill_doc_path), spaced_skill),
|
||||
]),
|
||||
..Default::default()
|
||||
};
|
||||
let path = skill_doc_path.display();
|
||||
let spaced_path = spaced_skill_doc_path.display();
|
||||
|
||||
for command in [
|
||||
format!("Get-Content {path}"),
|
||||
format!("Get-Content -Raw {path}"),
|
||||
format!("Get-Content \"{spaced_path}\""),
|
||||
format!("Get-Content -Raw \"{spaced_path}\""),
|
||||
] {
|
||||
let found = detect_implicit_skill_invocation_for_command(
|
||||
&outcome,
|
||||
&command,
|
||||
&test_path_buf("/tmp").abs(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
found.map(|value| value.name),
|
||||
Some("test-skill".to_string()),
|
||||
"command: {command}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn powershell_get_content_path_preserves_windows_backslashes() {
|
||||
assert_eq!(
|
||||
powershell_get_content_path(r#"Get-Content C:\skills\example\SKILL.md"#),
|
||||
Some(r#"C:\skills\example\SKILL.md"#)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skill_doc_read_detection_matches_absolute_path() {
|
||||
let skill_doc_path = test_path_buf("/tmp/skill-test/SKILL.md").abs();
|
||||
|
||||
Reference in New Issue
Block a user