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:
@@ -435,12 +435,44 @@ pub async fn install_missing_plugins(
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if missing.is_empty() {
|
if missing.is_empty() {
|
||||||
emit_plugin_event(
|
// Nothing to install, but still pin any @latest specs
|
||||||
emitter,
|
let all_specs: Vec<(String, String)> = summary
|
||||||
&task_id,
|
.plugins
|
||||||
PluginInstallEventKind::Completed,
|
.iter()
|
||||||
"Nothing to install — all plugins are already present",
|
.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(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,7 +550,10 @@ pub async fn install_missing_plugins(
|
|||||||
if exit_status.success() {
|
if exit_status.success() {
|
||||||
// Pin @latest specs to actual installed versions to avoid
|
// Pin @latest specs to actual installed versions to avoid
|
||||||
// opencode hitting the npm registry on every startup.
|
// 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()
|
.iter()
|
||||||
.map(|p| (p.name.clone(), p.declared_spec.clone()))
|
.map(|p| (p.name.clone(), p.declared_spec.clone()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|||||||
@@ -117,6 +117,10 @@ export function OpencodePluginsModal({
|
|||||||
|
|
||||||
const missingCount =
|
const missingCount =
|
||||||
summary?.plugins.filter((p) => p.status === "missing").length ?? 0
|
summary?.plugins.filter((p) => p.status === "missing").length ?? 0
|
||||||
|
const floatingCount =
|
||||||
|
summary?.plugins.filter((p) => p.declared_spec.endsWith("@latest"))
|
||||||
|
.length ?? 0
|
||||||
|
const hasActionablePlugins = missingCount > 0 || floatingCount > 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={handleClose}>
|
<Dialog open={open} onOpenChange={handleClose}>
|
||||||
@@ -209,7 +213,7 @@ export function OpencodePluginsModal({
|
|||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
disabled={isOperating || missingCount === 0}
|
disabled={isOperating || !hasActionablePlugins}
|
||||||
onClick={handleInstallAll}
|
onClick={handleInstallAll}
|
||||||
>
|
>
|
||||||
{stream.status === "running" ? (
|
{stream.status === "running" ? (
|
||||||
@@ -217,7 +221,9 @@ export function OpencodePluginsModal({
|
|||||||
) : (
|
) : (
|
||||||
<Download className="h-3.5 w-3.5 mr-1.5" />
|
<Download className="h-3.5 w-3.5 mr-1.5" />
|
||||||
)}
|
)}
|
||||||
{t("opencodePlugins.installAll")}
|
{missingCount > 0
|
||||||
|
? t("opencodePlugins.installAll")
|
||||||
|
: t("opencodePlugins.pinVersions")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|||||||
@@ -695,6 +695,7 @@
|
|||||||
"missing": "غير مثبّت"
|
"missing": "غير مثبّت"
|
||||||
},
|
},
|
||||||
"installAll": "تثبيت جميع الإضافات المفقودة",
|
"installAll": "تثبيت جميع الإضافات المفقودة",
|
||||||
|
"pinVersions": "تثبيت إصدارات @latest",
|
||||||
"install": "تثبيت",
|
"install": "تثبيت",
|
||||||
"uninstall": "إزالة",
|
"uninstall": "إزالة",
|
||||||
"refresh": "تحديث",
|
"refresh": "تحديث",
|
||||||
|
|||||||
@@ -695,6 +695,7 @@
|
|||||||
"missing": "Nicht installiert"
|
"missing": "Nicht installiert"
|
||||||
},
|
},
|
||||||
"installAll": "Alle fehlenden installieren",
|
"installAll": "Alle fehlenden installieren",
|
||||||
|
"pinVersions": "@latest-Versionen fixieren",
|
||||||
"install": "Installieren",
|
"install": "Installieren",
|
||||||
"uninstall": "Deinstallieren",
|
"uninstall": "Deinstallieren",
|
||||||
"refresh": "Aktualisieren",
|
"refresh": "Aktualisieren",
|
||||||
|
|||||||
@@ -695,6 +695,7 @@
|
|||||||
"missing": "Missing"
|
"missing": "Missing"
|
||||||
},
|
},
|
||||||
"installAll": "Install All Missing",
|
"installAll": "Install All Missing",
|
||||||
|
"pinVersions": "Pin @latest Versions",
|
||||||
"install": "Install",
|
"install": "Install",
|
||||||
"uninstall": "Uninstall",
|
"uninstall": "Uninstall",
|
||||||
"refresh": "Refresh",
|
"refresh": "Refresh",
|
||||||
|
|||||||
@@ -695,6 +695,7 @@
|
|||||||
"missing": "No instalado"
|
"missing": "No instalado"
|
||||||
},
|
},
|
||||||
"installAll": "Instalar todos los faltantes",
|
"installAll": "Instalar todos los faltantes",
|
||||||
|
"pinVersions": "Fijar versiones @latest",
|
||||||
"install": "Instalar",
|
"install": "Instalar",
|
||||||
"uninstall": "Desinstalar",
|
"uninstall": "Desinstalar",
|
||||||
"refresh": "Actualizar",
|
"refresh": "Actualizar",
|
||||||
|
|||||||
@@ -695,6 +695,7 @@
|
|||||||
"missing": "Non installé"
|
"missing": "Non installé"
|
||||||
},
|
},
|
||||||
"installAll": "Installer tous les manquants",
|
"installAll": "Installer tous les manquants",
|
||||||
|
"pinVersions": "Fixer les versions @latest",
|
||||||
"install": "Installer",
|
"install": "Installer",
|
||||||
"uninstall": "Désinstaller",
|
"uninstall": "Désinstaller",
|
||||||
"refresh": "Actualiser",
|
"refresh": "Actualiser",
|
||||||
|
|||||||
@@ -695,6 +695,7 @@
|
|||||||
"missing": "未インストール"
|
"missing": "未インストール"
|
||||||
},
|
},
|
||||||
"installAll": "不足プラグインをすべてインストール",
|
"installAll": "不足プラグインをすべてインストール",
|
||||||
|
"pinVersions": "@latest バージョンを固定",
|
||||||
"install": "インストール",
|
"install": "インストール",
|
||||||
"uninstall": "アンインストール",
|
"uninstall": "アンインストール",
|
||||||
"refresh": "更新",
|
"refresh": "更新",
|
||||||
|
|||||||
@@ -695,6 +695,7 @@
|
|||||||
"missing": "미설치"
|
"missing": "미설치"
|
||||||
},
|
},
|
||||||
"installAll": "누락된 플러그인 모두 설치",
|
"installAll": "누락된 플러그인 모두 설치",
|
||||||
|
"pinVersions": "@latest 버전 고정",
|
||||||
"install": "설치",
|
"install": "설치",
|
||||||
"uninstall": "제거",
|
"uninstall": "제거",
|
||||||
"refresh": "새로고침",
|
"refresh": "새로고침",
|
||||||
|
|||||||
@@ -695,6 +695,7 @@
|
|||||||
"missing": "Não instalado"
|
"missing": "Não instalado"
|
||||||
},
|
},
|
||||||
"installAll": "Instalar todos os ausentes",
|
"installAll": "Instalar todos os ausentes",
|
||||||
|
"pinVersions": "Fixar versões @latest",
|
||||||
"install": "Instalar",
|
"install": "Instalar",
|
||||||
"uninstall": "Desinstalar",
|
"uninstall": "Desinstalar",
|
||||||
"refresh": "Atualizar",
|
"refresh": "Atualizar",
|
||||||
|
|||||||
@@ -695,6 +695,7 @@
|
|||||||
"missing": "未安装"
|
"missing": "未安装"
|
||||||
},
|
},
|
||||||
"installAll": "安装全部缺失插件",
|
"installAll": "安装全部缺失插件",
|
||||||
|
"pinVersions": "固定 @latest 版本",
|
||||||
"install": "安装",
|
"install": "安装",
|
||||||
"uninstall": "卸载",
|
"uninstall": "卸载",
|
||||||
"refresh": "刷新",
|
"refresh": "刷新",
|
||||||
|
|||||||
@@ -695,6 +695,7 @@
|
|||||||
"missing": "未安裝"
|
"missing": "未安裝"
|
||||||
},
|
},
|
||||||
"installAll": "安裝全部缺失外掛",
|
"installAll": "安裝全部缺失外掛",
|
||||||
|
"pinVersions": "固定 @latest 版本",
|
||||||
"install": "安裝",
|
"install": "安裝",
|
||||||
"uninstall": "解除安裝",
|
"uninstall": "解除安裝",
|
||||||
"refresh": "重新整理",
|
"refresh": "重新整理",
|
||||||
|
|||||||
Reference in New Issue
Block a user