mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Generalize skill locator aliases across providers (#37488)
## What changed - Compact executor and orchestrator skill locators under metadata pressure, using provider-specific `e` and `o` aliases alongside host `r` aliases. - Derive alias roots from executor discovery paths and orchestrator namespaces while preserving host plugin root handling. - Centralize alias ordering, deduplication, and longest-prefix matching across skill providers. ## Testing - Cover alias planning, cross-platform executor roots, and host plugin discovery. GitOrigin-RevId: e7d15bd3891c08ae20170e96c4ad45c76d353707
This commit is contained in:
1 parent
27e4a05cd3
commit
ce22ea9712
12 files changed
+458
-218
No files matched your search
@@ -1,20 +1,17 @@
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::path::Component;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use codex_core_skills::MAX_SKILL_PROMPT_BYTES;
|
||||
use codex_protocol::protocol::SkillScope;
|
||||
use codex_utils_string::approx_token_count;
|
||||
use codex_utils_string::take_bytes_at_char_boundary;
|
||||
|
||||
use crate::aliases::AliasPlan;
|
||||
use crate::catalog::SkillCatalog;
|
||||
use crate::catalog::SkillCatalogEntry;
|
||||
use crate::catalog::SkillSourceKind;
|
||||
use crate::catalog_prompt::render_available_skills_body;
|
||||
use crate::fragments::AvailableSkillsInstructions;
|
||||
use crate::host_aliases::shared_host_alias_roots;
|
||||
|
||||
const DEFAULT_SKILL_METADATA_CHAR_BUDGET: usize = 8_000;
|
||||
const SKILL_METADATA_CONTEXT_WINDOW_PERCENT: usize = 2;
|
||||
@@ -693,12 +690,14 @@ fn build_aliased_combined_catalog(
|
||||
host_entries: &[&SkillCatalogEntry],
|
||||
budget: SkillMetadataBudget,
|
||||
) -> Option<CombinedAvailableSkillsRender> {
|
||||
let plan = build_alias_plan(host_entries, budget)?;
|
||||
if plan.table_cost >= budget.limit() {
|
||||
let plan = build_alias_plan(host_entries)?;
|
||||
let skill_root_lines = plan.root_lines();
|
||||
let table_cost = aliased_metadata_overhead_cost(budget, &skill_root_lines);
|
||||
if table_cost >= budget.limit() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let adjusted_limit = budget.limit().saturating_sub(plan.table_cost);
|
||||
let adjusted_limit = budget.limit().saturating_sub(table_cost);
|
||||
let adjusted_budget = match budget {
|
||||
SkillMetadataBudget::Tokens(_) => SkillMetadataBudget::Tokens(adjusted_limit),
|
||||
SkillMetadataBudget::Characters(_) => SkillMetadataBudget::Characters(adjusted_limit),
|
||||
@@ -717,7 +716,7 @@ fn build_aliased_combined_catalog(
|
||||
SkillLine::with_locator(
|
||||
entry,
|
||||
SkillCatalogRenderPolicy::CoreCompatible,
|
||||
render_skill_path_with_aliases(entry, &plan),
|
||||
render_skill_locator_with_aliases(entry, &plan),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
@@ -726,7 +725,7 @@ fn build_aliased_combined_catalog(
|
||||
orchestrator_lines,
|
||||
host_lines,
|
||||
adjusted_budget,
|
||||
plan.skill_root_lines,
|
||||
skill_root_lines,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -904,47 +903,12 @@ fn available_skills_fragment(
|
||||
.into_fragment(include_skills_usage_instructions)
|
||||
}
|
||||
|
||||
struct AliasPlan {
|
||||
skill_root_lines: Vec<String>,
|
||||
alias_root_by_display_root: HashMap<String, String>,
|
||||
root_aliases: HashMap<String, String>,
|
||||
table_cost: usize,
|
||||
}
|
||||
|
||||
fn build_aliased_catalog(
|
||||
entries: &[&SkillCatalogEntry],
|
||||
policy: SkillCatalogRenderPolicy,
|
||||
budget: SkillMetadataBudget,
|
||||
) -> Option<RenderedCatalog> {
|
||||
let plan = build_alias_plan(entries, budget)?;
|
||||
if plan.table_cost >= budget.limit() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let adjusted_limit = budget.limit().saturating_sub(plan.table_cost);
|
||||
let adjusted_budget = match budget {
|
||||
SkillMetadataBudget::Tokens(_) => SkillMetadataBudget::Tokens(adjusted_limit),
|
||||
SkillMetadataBudget::Characters(_) => SkillMetadataBudget::Characters(adjusted_limit),
|
||||
};
|
||||
let skill_lines = entries
|
||||
.iter()
|
||||
.map(|entry| {
|
||||
SkillLine::with_locator(entry, policy, render_skill_path_with_aliases(entry, &plan))
|
||||
})
|
||||
.collect();
|
||||
Some(render_catalog(
|
||||
skill_lines,
|
||||
adjusted_budget,
|
||||
plan.skill_root_lines,
|
||||
policy,
|
||||
))
|
||||
}
|
||||
|
||||
fn build_alias_plan(
|
||||
entries: &[&SkillCatalogEntry],
|
||||
budget: SkillMetadataBudget,
|
||||
) -> Option<AliasPlan> {
|
||||
// The shared alias prompt only describes host filesystem skills.
|
||||
// Alias instructions currently describe only host filesystem skills.
|
||||
if entries
|
||||
.iter()
|
||||
.any(|entry| entry.authority.kind != SkillSourceKind::Host)
|
||||
@@ -952,132 +916,71 @@ fn build_alias_plan(
|
||||
return None;
|
||||
}
|
||||
|
||||
let plugin_version_skill_counts = plugin_version_skill_counts_for_entries(entries);
|
||||
let mut alias_root_by_display_root = HashMap::new();
|
||||
let mut alias_roots = Vec::new();
|
||||
let mut seen = HashSet::new();
|
||||
let mut alias_ordered_entries = entries.to_vec();
|
||||
alias_ordered_entries
|
||||
.sort_by_key(|entry| entry.display_path_root_order().unwrap_or(usize::MAX));
|
||||
for entry in alias_ordered_entries {
|
||||
if entry.authority.kind != SkillSourceKind::Host {
|
||||
continue;
|
||||
}
|
||||
let Some(display_root) = entry.display_path_root() else {
|
||||
continue;
|
||||
};
|
||||
let alias_root =
|
||||
alias_root_for_display_root(Path::new(display_root), &plugin_version_skill_counts)
|
||||
.to_string_lossy()
|
||||
.replace('\\', "/");
|
||||
alias_root_by_display_root.insert(display_root.to_string(), alias_root.clone());
|
||||
if seen.insert(alias_root.clone()) {
|
||||
alias_roots.push(alias_root);
|
||||
}
|
||||
}
|
||||
if alias_roots.is_empty() {
|
||||
let plan = build_alias_plan(entries)?;
|
||||
let skill_root_lines = plan.root_lines();
|
||||
let table_cost = aliased_metadata_overhead_cost(budget, &skill_root_lines);
|
||||
if table_cost >= budget.limit() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let root_aliases = alias_roots
|
||||
let adjusted_limit = budget.limit().saturating_sub(table_cost);
|
||||
let adjusted_budget = match budget {
|
||||
SkillMetadataBudget::Tokens(_) => SkillMetadataBudget::Tokens(adjusted_limit),
|
||||
SkillMetadataBudget::Characters(_) => SkillMetadataBudget::Characters(adjusted_limit),
|
||||
};
|
||||
let skill_lines = entries
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, root)| (root.clone(), format!("r{index}")))
|
||||
.map(|entry| {
|
||||
SkillLine::with_locator(
|
||||
entry,
|
||||
policy,
|
||||
render_skill_locator_with_aliases(entry, &plan),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let skill_root_lines = alias_roots
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, root)| format!("- `r{index}` = `{root}`"))
|
||||
.collect::<Vec<_>>();
|
||||
let table_cost = aliased_metadata_overhead_cost(budget, &skill_root_lines);
|
||||
Some(AliasPlan {
|
||||
Some(render_catalog(
|
||||
skill_lines,
|
||||
adjusted_budget,
|
||||
skill_root_lines,
|
||||
alias_root_by_display_root,
|
||||
root_aliases,
|
||||
table_cost,
|
||||
})
|
||||
policy,
|
||||
))
|
||||
}
|
||||
|
||||
fn plugin_version_skill_counts_for_entries(
|
||||
entries: &[&SkillCatalogEntry],
|
||||
) -> HashMap<PathBuf, usize> {
|
||||
let mut counts = HashMap::new();
|
||||
for root in entries.iter().filter_map(|entry| {
|
||||
(entry.authority.kind == SkillSourceKind::Host)
|
||||
.then(|| entry.display_path_root())
|
||||
.flatten()
|
||||
}) {
|
||||
if let Some(plugin_version_base) = plugin_version_base(Path::new(root)) {
|
||||
let count = counts.entry(plugin_version_base).or_insert(0usize);
|
||||
*count = count.saturating_add(1);
|
||||
}
|
||||
fn build_alias_plan(entries: &[&SkillCatalogEntry]) -> Option<AliasPlan> {
|
||||
let source = &entries.first()?.authority.kind;
|
||||
if entries.iter().any(|entry| &entry.authority.kind != source) {
|
||||
return None;
|
||||
}
|
||||
counts
|
||||
}
|
||||
|
||||
fn alias_root_for_display_root(
|
||||
root: &Path,
|
||||
plugin_version_skill_counts: &HashMap<PathBuf, usize>,
|
||||
) -> PathBuf {
|
||||
let Some(plugin_version_base) = plugin_version_base(root) else {
|
||||
return root.to_path_buf();
|
||||
let prefix = match source {
|
||||
SkillSourceKind::Host => "r",
|
||||
SkillSourceKind::Executor => "e",
|
||||
SkillSourceKind::Orchestrator => "o",
|
||||
SkillSourceKind::Custom(_) => return None,
|
||||
};
|
||||
let skill_count = plugin_version_skill_counts
|
||||
.get(&plugin_version_base)
|
||||
.copied()
|
||||
.unwrap_or_default();
|
||||
if skill_count > 1 {
|
||||
root.to_path_buf()
|
||||
} else {
|
||||
plugin_marketplace_base(root).unwrap_or_else(|| root.to_path_buf())
|
||||
}
|
||||
}
|
||||
|
||||
fn plugin_marketplace_base(path: &Path) -> Option<PathBuf> {
|
||||
let mut candidate = path;
|
||||
while let Some(parent) = candidate.parent() {
|
||||
if parent.file_name()?.to_str()? == "cache"
|
||||
&& parent.parent()?.file_name()?.to_str()? == "plugins"
|
||||
{
|
||||
return Some(candidate.to_path_buf());
|
||||
}
|
||||
candidate = parent;
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn plugin_version_base(path: &Path) -> Option<PathBuf> {
|
||||
let marketplace_base = plugin_marketplace_base(path)?;
|
||||
let mut relative_components = path.strip_prefix(&marketplace_base).ok()?.components();
|
||||
let plugin = match relative_components.next()? {
|
||||
Component::Normal(plugin) => plugin,
|
||||
_ => return None,
|
||||
let mut alias_ordered_entries = entries.to_vec();
|
||||
alias_ordered_entries.sort_by_key(|entry| entry.alias_root_order().unwrap_or(usize::MAX));
|
||||
let roots = match source {
|
||||
SkillSourceKind::Host => shared_host_alias_roots(&alias_ordered_entries),
|
||||
SkillSourceKind::Executor | SkillSourceKind::Orchestrator => alias_ordered_entries
|
||||
.iter()
|
||||
.filter_map(|entry| entry.alias_root())
|
||||
.map(str::to_string)
|
||||
.collect(),
|
||||
SkillSourceKind::Custom(_) => return None,
|
||||
};
|
||||
let version = match relative_components.next()? {
|
||||
Component::Normal(version) => version,
|
||||
_ => return None,
|
||||
};
|
||||
Some(marketplace_base.join(plugin).join(version))
|
||||
let roots = roots.iter().map(String::as_str).collect::<Vec<_>>();
|
||||
|
||||
AliasPlan::build(prefix, &roots)
|
||||
}
|
||||
|
||||
fn render_skill_path_with_aliases(entry: &SkillCatalogEntry, plan: &AliasPlan) -> String {
|
||||
if entry.authority.kind != SkillSourceKind::Host {
|
||||
fn render_skill_locator_with_aliases(entry: &SkillCatalogEntry, plan: &AliasPlan) -> String {
|
||||
if entry.alias_root().is_none() {
|
||||
return entry.rendered_path().to_string();
|
||||
}
|
||||
let Some(display_root) = entry.display_path_root() else {
|
||||
return entry.rendered_path().to_string();
|
||||
};
|
||||
let Some(alias_root) = plan.alias_root_by_display_root.get(display_root) else {
|
||||
return entry.rendered_path().to_string();
|
||||
};
|
||||
let Some(alias) = plan.root_aliases.get(alias_root) else {
|
||||
return entry.rendered_path().to_string();
|
||||
};
|
||||
let Ok(relative_path) = Path::new(entry.rendered_path()).strip_prefix(alias_root) else {
|
||||
return entry.rendered_path().to_string();
|
||||
};
|
||||
let relative_path = relative_path.to_string_lossy().replace('\\', "/");
|
||||
format!("{alias}/{relative_path}")
|
||||
let locator = entry.rendered_path().replace('\\', "/");
|
||||
plan.shorten(&locator)
|
||||
.unwrap_or_else(|| entry.rendered_path().to_string())
|
||||
}
|
||||
|
||||
fn aliased_metadata_overhead_cost(
|
||||
|
||||
Reference in new issue
Block a user