mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
## What changed - Load and cache the host skill provider catalog during world-state contribution. - Render host skill listings from that catalog with Core-compatible budgeting, while preserving Core's full prompt injection for selected host skills. - Reuse the cached host catalog for shadow selection, including when skill listings are disabled. - Preserve an empty Core-compatible skills fragment when every entry exceeds the metadata budget, and make budget warnings independent of the configured percentage. ## Testing - Cover provider-backed host listings, selected-skill prompt injection, shadow selection, disabled listings, oversized prompts, empty fragments, metrics, and warnings. GitOrigin-RevId: b6b2d8ea14386356094cff5783d121d74657e9e3
104 lines
3.1 KiB
Rust
104 lines
3.1 KiB
Rust
use codex_core_skills::SKILLS_HOW_TO_USE_WITH_ABSOLUTE_PATHS;
|
|
use codex_core_skills::SKILLS_HOW_TO_USE_WITH_ALIASES;
|
|
use codex_core_skills::render_available_skills_body;
|
|
use codex_extension_api::ContextualUserFragment;
|
|
use codex_protocol::protocol::SKILLS_INSTRUCTIONS_CLOSE_TAG;
|
|
use codex_protocol::protocol::SKILLS_INSTRUCTIONS_OPEN_TAG;
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
pub(crate) struct AvailableSkillsInstructions {
|
|
skill_root_lines: Vec<String>,
|
|
skill_lines: Vec<String>,
|
|
}
|
|
|
|
impl AvailableSkillsInstructions {
|
|
pub(crate) fn from_skill_lines(
|
|
skill_root_lines: Vec<String>,
|
|
mut skill_lines: Vec<String>,
|
|
include_skills_usage_instructions: bool,
|
|
) -> Self {
|
|
if include_skills_usage_instructions {
|
|
skill_lines.push("### How to use skills".to_string());
|
|
let instructions = if skill_root_lines.is_empty() {
|
|
SKILLS_HOW_TO_USE_WITH_ABSOLUTE_PATHS
|
|
} else {
|
|
SKILLS_HOW_TO_USE_WITH_ALIASES
|
|
};
|
|
skill_lines.push(instructions.to_string());
|
|
}
|
|
Self {
|
|
skill_root_lines,
|
|
skill_lines,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ContextualUserFragment for AvailableSkillsInstructions {
|
|
fn role(&self) -> &'static str {
|
|
"developer"
|
|
}
|
|
|
|
fn markers(&self) -> (&'static str, &'static str) {
|
|
Self::type_markers()
|
|
}
|
|
|
|
fn type_markers() -> (&'static str, &'static str) {
|
|
(SKILLS_INSTRUCTIONS_OPEN_TAG, SKILLS_INSTRUCTIONS_CLOSE_TAG)
|
|
}
|
|
|
|
fn body(&self) -> String {
|
|
render_available_skills_body(&self.skill_root_lines, &self.skill_lines)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
pub(crate) struct SkillInstructions {
|
|
pub(crate) name: String,
|
|
pub(crate) path: String,
|
|
pub(crate) contents: String,
|
|
pub(crate) executor_resource_access: Option<ExecutorSkillResourceAccess>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
pub(crate) struct ExecutorSkillResourceAccess {
|
|
pub(crate) authority_id: String,
|
|
pub(crate) package: String,
|
|
pub(crate) main_resource: String,
|
|
}
|
|
|
|
impl ContextualUserFragment for SkillInstructions {
|
|
fn role(&self) -> &'static str {
|
|
"user"
|
|
}
|
|
|
|
fn markers(&self) -> (&'static str, &'static str) {
|
|
Self::type_markers()
|
|
}
|
|
|
|
fn type_markers() -> (&'static str, &'static str) {
|
|
("<skill>", "</skill>")
|
|
}
|
|
|
|
fn body(&self) -> String {
|
|
let name = &self.name;
|
|
let path = &self.path;
|
|
let contents = &self.contents;
|
|
let resource_access = self
|
|
.executor_resource_access
|
|
.as_ref()
|
|
.map(|access| {
|
|
let metadata = serde_json::json!({
|
|
"authority": {
|
|
"kind": "executor",
|
|
"id": access.authority_id,
|
|
},
|
|
"package": access.package,
|
|
"main_resource": access.main_resource,
|
|
});
|
|
format!("\n<resource_access>{metadata}</resource_access>")
|
|
})
|
|
.unwrap_or_default();
|
|
format!("\n<name>{name}</name>\n<path>{path}</path>{resource_access}\n{contents}\n")
|
|
}
|
|
}
|