Move host skill prompt injection into the skills extension (#37503)

## What changed

- Add `HostSkillsSnapshot::load_skill_prompts` so the skills extension owns reading and rendering selected host skills.
- Keep explicit invocation telemetry, unreadable-skill warnings, plugin prompt ordering, and suppression of host prompts superseded by provider prompts.
- Remove the legacy prompt injection and fragment implementation from `codex-core-skills`.

## Testing

- Cover prompt truncation without an installed skills extension, skill/plugin ordering, selective provider supersession, unreadable skills, and contextual fragment detection.

GitOrigin-RevId: 9c8b84ad54b90d174abc287ab49cc5a231e9e1aa
This commit is contained in:
felixxia-oai authored and copyberry committed 2026-08-07 21:04:16 +00:00
1 parent 8e4b10446e
commit beac16cccd
22 files changed
+553 -299

No files matched your search

+48 -5
View File
@@ -3,6 +3,7 @@ use crate::session::session::Session;
use crate::session::turn_context::TurnContext;
use codex_analytics::InvocationType;
use codex_analytics::SkillInvocation;
use codex_analytics::TrackEventsContext;
use codex_analytics::build_track_events_context;
use codex_extension_api::SkillInvocationInput;
use codex_extension_api::SkillInvocationKind;
@@ -15,15 +16,12 @@ use tokio::sync::Mutex;
pub use codex_core_skills::SkillError;
pub use codex_core_skills::SkillLoadOutcome;
pub use codex_core_skills::build_skill_name_counts;
pub use codex_core_skills::detect_implicit_skill_invocation_for_command;
pub use codex_core_skills::injection;
pub use codex_core_skills::injection::SkillInjections;
pub use codex_core_skills::injection::build_skill_injections;
pub use codex_core_skills::model;
pub use codex_skills::SkillMetadata;
pub use codex_skills::SkillPolicy;
pub use codex_skills::build_skill_name_counts;
pub use codex_skills::collect_explicit_skill_mentions;
pub use codex_skills::detect_implicit_skill_invocation_for_command;
pub use codex_skills_extension::HostSkillsLoadInput;
pub use codex_skills_extension::HostSkillsService;
pub use codex_skills_extension::bundled_skills_enabled_from_stack;
@@ -43,6 +41,51 @@ pub(crate) fn skills_load_input_from_config(
)
}
pub(crate) fn emit_explicit_skill_invocations(
sess: &Session,
turn_context: &TurnContext,
mentioned_skills: &[SkillMetadata],
injected_skills: &[SkillMetadata],
tracking: TrackEventsContext,
) {
let injected_skill_paths = injected_skills
.iter()
.map(|skill| &skill.path_to_skills_md)
.collect::<HashSet<_>>();
for skill in mentioned_skills {
let skill_name_tag = sanitize_metric_tag_value(skill.name.as_str());
let status = if injected_skill_paths.contains(&skill.path_to_skills_md) {
"ok"
} else {
"error"
};
turn_context.session_telemetry.counter(
"codex.skill.injected",
/*inc*/ 1,
&[
("status", status),
("skill", skill_name_tag.as_str()),
("invoke_type", "explicit"),
],
);
}
let invocations = injected_skills
.iter()
.map(|skill| SkillInvocation {
skill_name: skill.name.clone(),
skill_scope: skill.scope,
skill_path: skill.path_to_skills_md.to_path_buf(),
plugin_id: skill.plugin_id.clone(),
remote_plugin_id: skill.remote_plugin_id.clone(),
invocation_type: InvocationType::Explicit,
})
.collect();
sess.services
.analytics_events_client
.track_skill_invocations(tracking, invocations);
}
pub(crate) async fn maybe_emit_implicit_skill_invocation(
sess: &Session,
turn_context: &TurnContext,