fix(acp): pin @latest for all plugins and enable button when only floating versions exist

- install_missing_plugins now pins ALL @latest specs (not just newly installed)
- When nothing is missing but @latest exists, the pin-only path runs
- Modal button switches to 'Pin @latest Versions' when no missing plugins
- Added pinVersions i18n key for 10 languages
This commit is contained in:
xintaofei
2026-04-12 11:56:55 +08:00
parent 4397b0eae7
commit 023e4c5514
12 changed files with 60 additions and 9 deletions

View File

@@ -435,12 +435,44 @@ pub async fn install_missing_plugins(
.collect();
if missing.is_empty() {
emit_plugin_event(
emitter,
&task_id,
PluginInstallEventKind::Completed,
"Nothing to install — all plugins are already present",
);
// Nothing to install, but still pin any @latest specs
let all_specs: Vec<(String, String)> = summary
.plugins
.iter()
.map(|p| (p.name.clone(), p.declared_spec.clone()))
.collect();
match pin_latest_specs(&summary.config_path, &summary.cache_dir, &all_specs) {
Ok(n) if n > 0 => {
emit_plugin_event(
emitter,
&task_id,
PluginInstallEventKind::Log,
format!("Pinned {n} @latest plugin(s) to installed versions in opencode.json"),
);
emit_plugin_event(
emitter,
&task_id,
PluginInstallEventKind::Completed,
format!("Pinned {n} @latest plugin(s) — no missing plugins to install"),
);
}
Err(e) => {
emit_plugin_event(
emitter,
&task_id,
PluginInstallEventKind::Failed,
format!("Failed to pin @latest versions: {e}"),
);
}
_ => {
emit_plugin_event(
emitter,
&task_id,
PluginInstallEventKind::Completed,
"Nothing to install — all plugins are already present",
);
}
}
return Ok(());
}
@@ -518,7 +550,10 @@ pub async fn install_missing_plugins(
if exit_status.success() {
// Pin @latest specs to actual installed versions to avoid
// opencode hitting the npm registry on every startup.
let spec_pairs: Vec<(String, String)> = missing
// Pin ALL plugins (not just the ones we installed), so already-installed
// @latest plugins also get pinned.
let spec_pairs: Vec<(String, String)> = summary
.plugins
.iter()
.map(|p| (p.name.clone(), p.declared_spec.clone()))
.collect();