Keep thread skill inspection cache-neutral

This commit is contained in:
jif-oai
2026-07-09 13:20:23 +01:00
parent 994ce4e312
commit abd6d5355c
3 changed files with 68 additions and 15 deletions
@@ -508,6 +508,7 @@ impl CatalogRequestProcessor {
Some(thread_id) => self.thread_skills(thread_id).await?,
None => (Vec::new(), Vec::new()),
};
let inspect_thread = thread_id.is_some();
let config = self.load_latest_config(/*fallback_cwd*/ None).await?;
let auth = self.auth_manager.auth().await;
@@ -521,7 +522,7 @@ impl CatalogRequestProcessor {
.environment_manager()
.default_environment()
.map(|environment| {
if thread_id.is_some() {
if inspect_thread {
environment.get_filesystem_without_reconnect()
} else {
environment.get_filesystem()
@@ -568,9 +569,15 @@ impl CatalogRequestProcessor {
config_layer_stack,
config.bundled_skills_enabled(),
);
let snapshot = skills_service
.snapshot_for_cwd(&skills_input, force_reload, fs)
.await;
let snapshot = if inspect_thread {
skills_service
.inspect_snapshot_for_cwd(&skills_input, force_reload, fs)
.await
} else {
skills_service
.snapshot_for_cwd(&skills_input, force_reload, fs)
.await
};
let outcome = snapshot.outcome();
let errors = errors_to_info(&outcome.errors);
let skills = skills_to_info(&outcome.skills, &outcome.disabled_paths);
@@ -210,6 +210,25 @@ async fn selected_capability_stack_tracks_environment_availability_and_resume()
(Vec::new(), Vec::new())
);
exec_server_proxy.resume()?;
wait_for_selected_mcp_server(&mut app_server, &inspection_thread_id).await?;
let request_id = app_server
.send_skills_list_request(SkillsListParams {
cwds: Vec::new(),
force_reload: false,
thread_id: None,
})
.await?;
let response = timeout(
READ_TIMEOUT,
app_server.read_stream_until_response_message(RequestId::Integer(request_id)),
)
.await??;
let SkillsListResponse { data, .. } = to_response(response)?;
assert!(
data.iter()
.any(|entry| { entry.skills.iter().any(|skill| skill.name == SKILL_NAME) })
);
exec_server.kill().await?;
drop(app_server);
+38 -11
View File
@@ -180,8 +180,43 @@ impl SkillsService {
return snapshot;
}
let snapshot = self.load_snapshot_for_cwd(input, fs).await;
if use_cwd_cache {
let mut cache = self
.cache_by_cwd
.write()
.unwrap_or_else(std::sync::PoisonError::into_inner);
cache.insert(input.cwd.clone(), snapshot.clone());
}
snapshot
}
/// Loads a cwd snapshot without updating the shared cwd cache.
///
/// Existing cached data can still be reused unless `force_reload` is set.
pub async fn inspect_snapshot_for_cwd(
&self,
input: &SkillsLoadInput,
force_reload: bool,
fs: Option<Arc<dyn ExecutorFileSystem>>,
) -> HostSkillsSnapshot {
if fs.is_some()
&& !force_reload
&& let Some(snapshot) = self.cached_snapshot_for_cwd(&input.cwd)
{
return snapshot;
}
self.load_snapshot_for_cwd(input, fs).await
}
async fn load_snapshot_for_cwd(
&self,
input: &SkillsLoadInput,
fs: Option<Arc<dyn ExecutorFileSystem>>,
) -> HostSkillsSnapshot {
let mut roots = skill_roots(
fs.clone(),
fs,
&input.config_layer_stack,
&input.cwd,
input.effective_skill_roots.clone(),
@@ -192,18 +227,10 @@ impl SkillsService {
roots.retain(|root| root.scope != SkillScope::System);
}
let skill_config_rules = skill_config_rules_from_stack(&input.config_layer_stack);
let snapshot = HostSkillsSnapshot::new(Arc::new(
HostSkillsSnapshot::new(Arc::new(
self.build_skill_outcome(input, roots, &skill_config_rules)
.await,
));
if use_cwd_cache {
let mut cache = self
.cache_by_cwd
.write()
.unwrap_or_else(std::sync::PoisonError::into_inner);
cache.insert(input.cwd.clone(), snapshot.clone());
}
snapshot
))
}
#[instrument(level = "trace", skip_all)]