Store turn skill state in extension data (#36740)

## What changed

- Store each turn's host skills snapshot in `ExtensionData` and expose it through
  `TurnContext::skills_snapshot`.
- Lazily keep implicit skill invocation deduplication state in the same turn-scoped
  store.
- Carry the skills snapshot into review turns without a separate
  `TurnSkillsContext` field.

GitOrigin-RevId: d71579b5d230bd0b5f3c2ad062861f74d614d88c
This commit is contained in:
jif authored and copyberry committed 2026-08-03 11:00:40 +00:00
1 parent d6407d7359
commit 79479cdf09
6 files changed
+26 -38

No files matched your search

+10 -6
View File
@@ -10,6 +10,8 @@ use codex_otel::sanitize_metric_tag_value;
use codex_protocol::protocol::SkillScope;
use codex_utils_absolute_path::AbsolutePathBuf;
use codex_utils_plugins::PluginSkillRoot;
use std::collections::HashSet;
use tokio::sync::Mutex;
pub use codex_core_skills::SkillError;
pub use codex_core_skills::SkillLoadOutcome;
@@ -31,6 +33,9 @@ pub use codex_core_skills::system;
pub use codex_skills::SkillMetadata;
pub use codex_skills::SkillPolicy;
#[derive(Debug, Default)]
struct ImplicitSkillInvocations(Mutex<HashSet<String>>);
pub(crate) fn skills_load_input_from_config(
config: &Config,
effective_skill_roots: Vec<PluginSkillRoot>,
@@ -50,7 +55,7 @@ pub(crate) async fn maybe_emit_implicit_skill_invocation(
workdir: &AbsolutePathBuf,
) {
let Some(candidate) = detect_implicit_skill_invocation_for_command(
turn_context.turn_skills.snapshot.outcome(),
turn_context.skills_snapshot().outcome(),
command,
workdir,
) else {
@@ -74,11 +79,10 @@ pub(crate) async fn maybe_emit_implicit_skill_invocation(
let skill_name = invocation.skill_name.clone();
let seen_key = format!("{skill_scope}:{skill_path}:{skill_name}");
let inserted = {
let mut seen_skills = turn_context
.turn_skills
.implicit_invocation_seen_skills
.lock()
.await;
let skill_invocations = turn_context
.extension_data
.get_or_init(ImplicitSkillInvocations::default);
let mut seen_skills = skill_invocations.0.lock().await;
seen_skills.insert(seen_key)
};
if !inserted {