дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 19:25:54 +02:00
fix(agents): notify subscribers when a session report changes the cached provider config (#2308)
* fix(java): pass m2e an effective settings file carrying the configured local repository (#1739) m2e resolves the local repository from the Maven settings XML, never from -Dmaven.repo.local, so JDTLS imports kept downloading into ~/.m2/repository even when the IDE's own mvn runs honored the configured path. When a local repository is configured but the user settings lack <localRepository>, derive an effective settings file under <root>/.openidea/ and pass it as java.configuration.maven.userSettings. Settings that already declare <localRepository> are passed through untouched. * fix(agents): notify subscribers when a session report changes the cached provider config (#1490) Session reports (session/new, session/load, turn updates) and CLI discovery funnel through Shared::remember_inner, which cached new model lists but never emitted AgentEvent::Providers. The composer therefore kept showing a stale model list until the next task's busy-to-idle refresh. Emit Providers when the cache actually changes; unchanged reports stay silent, and the cache lock is released before invoking the sink. fetch_settings' unconditional emit is now covered by remember_discovered and removed.
Цей коміт міститься в:
1 джерело
660587a6fe
коміт
2680ba8463
2 files changed
+53
-1
No files matched your search
@@ -169,8 +169,10 @@ impl Shared {
|
||||
let commands = config::commands_of(&json!({ "availableCommands": commands }), &spec.id);
|
||||
let options = config::options_of(&json!({ "configOptions": options }));
|
||||
let _ = tokio::task::spawn_blocking(move || {
|
||||
// Notifies subscribers itself when the discovery
|
||||
// changed the cached config; unchanged results
|
||||
// stay silent.
|
||||
shared.remember_discovered(&spec.id, &options, &commands);
|
||||
shared.emit(AgentEvent::Providers);
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@@ -253,6 +255,13 @@ impl Shared {
|
||||
{
|
||||
tracing::warn!("saving agent settings: {e}");
|
||||
}
|
||||
// The cached provider config actually changed (a session report, discovery,
|
||||
// or a turn update): tell subscribers to re-list, so a changed model list
|
||||
// reaches the composer without waiting for the next task (#1490). Unchanged
|
||||
// reports stay silent, so routine session traffic emits nothing. The cache
|
||||
// lock is released first; the sink never runs under it.
|
||||
drop(cache);
|
||||
self.emit(AgentEvent::Providers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2146,6 +2146,49 @@ async fn reload_providers_updates_registry_install_clears_stale_probes_and_notif
|
||||
assert!(probe.error.is_none());
|
||||
}
|
||||
|
||||
/// A session report that changes the cached provider config notifies subscribers,
|
||||
/// so the composer re-lists models without waiting for the next task (#1490).
|
||||
/// Reports that change nothing stay silent.
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn remembered_config_changes_notify_subscribers_once() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let mgr = manager(tmp.path(), Arc::new(FakeAgent::default()));
|
||||
let events = Arc::new(Mutex::new(Vec::new()));
|
||||
let sink = events.clone();
|
||||
mgr.subscribe(Arc::new(move |e| sink.lock().push(e)));
|
||||
events.lock().clear();
|
||||
|
||||
let reported = config::options_of(&json!({ "configOptions": [
|
||||
{ "id": "model", "category": "model", "type": "select", "currentValue": "default",
|
||||
"options": [{ "value": "default" }, { "value": "custom-opus" }] },
|
||||
] }));
|
||||
mgr.shared.remember("claude", Some(&reported), None, Some("default"));
|
||||
assert!(
|
||||
events.lock().iter().any(|ev| matches!(ev, AgentEvent::Providers)),
|
||||
"a first report changing the cache notifies subscribers"
|
||||
);
|
||||
events.lock().clear();
|
||||
|
||||
// The same report again: the cache is unchanged, so subscribers hear nothing.
|
||||
mgr.shared.remember("claude", Some(&reported), None, Some("default"));
|
||||
assert!(events.lock().is_empty(), "an unchanged report must stay silent");
|
||||
|
||||
// A changed model list notifies again, and providers() serves the new list.
|
||||
let updated = config::options_of(&json!({ "configOptions": [
|
||||
{ "id": "model", "category": "model", "type": "select", "currentValue": "default",
|
||||
"options": [{ "value": "default" }, { "value": "custom-opus" }, { "value": "custom-sonnet" }] },
|
||||
] }));
|
||||
mgr.shared.remember("claude", Some(&updated), None, Some("default"));
|
||||
assert!(
|
||||
events.lock().iter().any(|ev| matches!(ev, AgentEvent::Providers)),
|
||||
"a changed model list notifies subscribers"
|
||||
);
|
||||
let claude = mgr.providers().into_iter().find(|p| p.id == "claude").unwrap();
|
||||
let model = claude.config.iter().find(|o| o.category.as_deref() == Some("model")).unwrap();
|
||||
let values: Vec<_> = model.values.iter().map(|v| v.value.as_str()).collect();
|
||||
assert_eq!(values, ["default", "custom-opus", "custom-sonnet"]);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn idle_agents_stop_and_resume_their_session_on_the_next_message() {
|
||||
let new = || NewAgentTask {
|
||||
|
||||
Reference in new issue
Заблокувати користувача