@cats-inc/cats-platform 0.2.8 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -1
- package/build/desktop/bootstrapPage.d.ts.map +1 -1
- package/build/desktop/bootstrapPage.js +26 -129
- package/build/desktop/bootstrapPage.js.map +1 -1
- package/build/desktop/cliInventoryProbe.d.ts +6 -0
- package/build/desktop/cliInventoryProbe.d.ts.map +1 -1
- package/build/desktop/cliInventoryProbe.js +6 -3
- package/build/desktop/cliInventoryProbe.js.map +1 -1
- package/build/desktop/contracts.d.ts +2 -0
- package/build/desktop/contracts.d.ts.map +1 -1
- package/build/desktop/contracts.js.map +1 -1
- package/build/desktop/main.js +95 -41
- package/build/desktop/main.js.map +1 -1
- package/build/desktop/preload.cjs +8 -6
- package/build/desktop/preload.cjs.map +1 -1
- package/build/desktop/providerManager.d.ts +46 -0
- package/build/desktop/providerManager.d.ts.map +1 -0
- package/build/desktop/providerManager.js +220 -0
- package/build/desktop/providerManager.js.map +1 -0
- package/build/desktop/providerSelection.d.ts +1 -0
- package/build/desktop/providerSelection.d.ts.map +1 -1
- package/build/desktop/providerSelection.js +7 -1
- package/build/desktop/providerSelection.js.map +1 -1
- package/build/desktop/setupAssets.d.ts.map +1 -1
- package/build/desktop/setupAssets.js +12 -0
- package/build/desktop/setupAssets.js.map +1 -1
- package/build/desktop/setupAudit.d.ts +3 -1
- package/build/desktop/setupAudit.d.ts.map +1 -1
- package/build/desktop/setupAudit.js +12 -8
- package/build/desktop/setupAudit.js.map +1 -1
- package/build/desktop/setupBridge.js +1 -1
- package/build/desktop/setupBridge.js.map +1 -1
- package/build/desktop/setupPrerequisites.d.ts +11 -0
- package/build/desktop/setupPrerequisites.d.ts.map +1 -0
- package/build/desktop/setupPrerequisites.js +47 -0
- package/build/desktop/setupPrerequisites.js.map +1 -0
- package/build/renderer/assets/ActiveSessionPermissionChip-BugyYoVY.js +1 -0
- package/build/renderer/assets/{App-BZA23O2J.js → App-1MFRMMld.js} +1 -1
- package/build/renderer/assets/{App-YqprEL2n.js → App-BWgnfutX.js} +1 -1
- package/build/renderer/assets/{App-rGw9J8PZ.js → App-Cm_tok6f.js} +1 -1
- package/build/renderer/assets/{WorkspaceAppRoutes-BCHCikmJ.js → WorkspaceAppRoutes-B8U5FWao.js} +1 -1
- package/build/renderer/assets/app-CqnsY5ed.css +1 -0
- package/build/renderer/assets/app-DTDTNtih.js +85 -0
- package/build/renderer/assets/{client-BdGHAUoK.js → client-DREGSZqQ.js} +1 -1
- package/build/renderer/assets/conversationSidebarRecentEntries-y_bEg3Cp.js +6 -0
- package/build/renderer/assets/{screenshotOverlay-DfBcolX-.js → screenshotOverlay-EF07cXvw.js} +1 -1
- package/build/renderer/assets/{useDraftSessionChips-D9BX6X92.js → useDraftSessionChips-BD6ZGG_y.js} +1 -1
- package/build/renderer/desktop/overlay/index.html +2 -2
- package/build/renderer/index.html +3 -3
- package/build/server/app/renderer/auth/api.d.ts.map +1 -1
- package/build/server/app/renderer/auth/api.js +4 -1
- package/build/server/app/renderer/auth/api.js.map +1 -1
- package/build/server/app/renderer/providerCatalogClient.d.ts.map +1 -1
- package/build/server/app/renderer/providerCatalogClient.js +19 -6
- package/build/server/app/renderer/providerCatalogClient.js.map +1 -1
- package/build/server/app/renderer/providerClientInvalidation.d.ts +6 -0
- package/build/server/app/renderer/providerClientInvalidation.d.ts.map +1 -0
- package/build/server/app/renderer/providerClientInvalidation.js +12 -0
- package/build/server/app/renderer/providerClientInvalidation.js.map +1 -0
- package/build/server/app/renderer/providerReadLoop.d.ts +5 -0
- package/build/server/app/renderer/providerReadLoop.d.ts.map +1 -0
- package/build/server/app/renderer/providerReadLoop.js +52 -0
- package/build/server/app/renderer/providerReadLoop.js.map +1 -0
- package/build/server/app/renderer/providerRegistryClient.d.ts +2 -1
- package/build/server/app/renderer/providerRegistryClient.d.ts.map +1 -1
- package/build/server/app/renderer/providerRegistryClient.js +33 -17
- package/build/server/app/renderer/providerRegistryClient.js.map +1 -1
- package/build/server/app/server/authGatePolicy.js +7 -0
- package/build/server/app/server/authGatePolicy.js.map +1 -1
- package/build/server/app/server/shutdown.d.ts.map +1 -1
- package/build/server/app/server/shutdown.js +3 -1
- package/build/server/app/server/shutdown.js.map +1 -1
- package/build/server/app/server/startup.d.ts +4 -3
- package/build/server/app/server/startup.d.ts.map +1 -1
- package/build/server/app/server/startup.js +8 -0
- package/build/server/app/server/startup.js.map +1 -1
- package/build/server/app/server/subscribeRoutes.d.ts.map +1 -1
- package/build/server/app/server/subscribeRoutes.js +5 -3
- package/build/server/app/server/subscribeRoutes.js.map +1 -1
- package/build/server/design/components/providerModelFieldsSupport.d.ts +2 -21
- package/build/server/design/components/providerModelFieldsSupport.d.ts.map +1 -1
- package/build/server/design/components/providerModelFieldsSupport.js +32 -36
- package/build/server/design/components/providerModelFieldsSupport.js.map +1 -1
- package/build/server/design/components/useProviderCatalogState.d.ts +1 -2
- package/build/server/design/components/useProviderCatalogState.d.ts.map +1 -1
- package/build/server/design/components/useProviderCatalogState.js +71 -152
- package/build/server/design/components/useProviderCatalogState.js.map +1 -1
- package/build/server/design/components/useProviderModelFieldActions.js +2 -2
- package/build/server/design/components/useProviderModelFieldActions.js.map +1 -1
- package/build/server/design/components/useProviderRegistryState.d.ts +1 -7
- package/build/server/design/components/useProviderRegistryState.d.ts.map +1 -1
- package/build/server/design/components/useProviderRegistryState.js +41 -91
- package/build/server/design/components/useProviderRegistryState.js.map +1 -1
- package/build/server/design/components/useProviderTargetReconciliation.d.ts +1 -0
- package/build/server/design/components/useProviderTargetReconciliation.d.ts.map +1 -1
- package/build/server/design/components/useProviderTargetReconciliation.js +1 -1
- package/build/server/design/components/useProviderTargetReconciliation.js.map +1 -1
- package/build/server/index.js +30 -0
- package/build/server/index.js.map +1 -1
- package/build/server/platform/orchestration/entitySubscriptions/channel.d.ts +2 -1
- package/build/server/platform/orchestration/entitySubscriptions/channel.d.ts.map +1 -1
- package/build/server/platform/orchestration/entitySubscriptions/channel.js +3 -18
- package/build/server/platform/orchestration/entitySubscriptions/channel.js.map +1 -1
- package/build/server/platform/orchestration/entitySubscriptions/index.d.ts +1 -0
- package/build/server/platform/orchestration/entitySubscriptions/index.d.ts.map +1 -1
- package/build/server/platform/orchestration/entitySubscriptions/index.js.map +1 -1
- package/build/server/products/chat/api/routeSupport.d.ts +9 -1
- package/build/server/products/chat/api/routeSupport.d.ts.map +1 -1
- package/build/server/products/chat/api/routeSupport.js +22 -0
- package/build/server/products/chat/api/routeSupport.js.map +1 -1
- package/build/server/products/chat/state/model/readModels.d.ts +1 -0
- package/build/server/products/chat/state/model/readModels.d.ts.map +1 -1
- package/build/server/products/chat/state/model/readModels.js +2 -1
- package/build/server/products/chat/state/model/readModels.js.map +1 -1
- package/build/server/products/shared/renderer/api/appShell.d.ts +1 -0
- package/build/server/products/shared/renderer/api/appShell.d.ts.map +1 -1
- package/build/server/products/shared/renderer/api/appShell.js +9 -0
- package/build/server/products/shared/renderer/api/appShell.js.map +1 -1
- package/build/server/runtime/client.d.ts.map +1 -1
- package/build/server/runtime/client.js +5 -1
- package/build/server/runtime/client.js.map +1 -1
- package/build/server/runtime/setup.d.ts +4 -0
- package/build/server/runtime/setup.d.ts.map +1 -1
- package/build/server/runtime/setup.js +3 -1
- package/build/server/runtime/setup.js.map +1 -1
- package/build/server/server/routes/providers.d.ts.map +1 -1
- package/build/server/server/routes/providers.js +21 -50
- package/build/server/server/routes/providers.js.map +1 -1
- package/build/server/shared/cliInteraction.d.ts +17 -0
- package/build/server/shared/cliInteraction.d.ts.map +1 -0
- package/build/server/shared/cliInteraction.js +102 -0
- package/build/server/shared/cliInteraction.js.map +1 -0
- package/build/server/shared/desktopRecoveryBridge.d.ts +2 -1
- package/build/server/shared/desktopRecoveryBridge.d.ts.map +1 -1
- package/build/server/shared/desktopRecoveryBridge.js.map +1 -1
- package/build/server/shared/providerCatalogData.d.ts +168 -96
- package/build/server/shared/providerCatalogData.d.ts.map +1 -1
- package/build/server/shared/providerCatalogData.js +68 -42
- package/build/server/shared/providerCatalogData.js.map +1 -1
- package/build/server/shared/providerRegistryWarnings.d.ts +4 -0
- package/build/server/shared/providerRegistryWarnings.d.ts.map +1 -1
- package/build/server/shared/providerRegistryWarnings.js +7 -0
- package/build/server/shared/providerRegistryWarnings.js.map +1 -1
- package/package.json +13 -6
- package/packages/provider-setup/manager.d.ts +79 -0
- package/packages/provider-setup/manager.js +441 -0
- package/scripts/README.md +23 -0
- package/scripts/build-desktop-installer.mjs +124 -16
- package/scripts/dev-server.mjs +4 -1
- package/scripts/linux/install-github-cli.sh +5 -0
- package/scripts/linux/install-node.sh +9 -3
- package/scripts/linux/node-cli-common.sh +87 -48
- package/scripts/linux/provider-cli-common.sh +80 -105
- package/scripts/linux/provider-version-common.sh +247 -0
- package/scripts/linux/test-linux-package-smoke.sh +2 -0
- package/scripts/linux/verified-npm-update.sh +20 -0
- package/scripts/macos/install-github-cli.sh +5 -0
- package/scripts/macos/install-node.sh +9 -3
- package/scripts/macos/node-cli-common.sh +87 -48
- package/scripts/macos/provider-cli-common.sh +80 -105
- package/scripts/macos/provider-version-common.sh +247 -0
- package/scripts/macos/test-macos-package-smoke.sh +2 -0
- package/scripts/macos/verified-npm-update.sh +20 -0
- package/scripts/testing/conversation-navigation-smoke-electron.cjs +134 -0
- package/scripts/testing/conversation-navigation-smoke-renderer.tsx +102 -0
- package/scripts/testing/conversation-navigation-smoke.mjs +67 -0
- package/scripts/validate-release-assets.mjs +4 -1
- package/scripts/windows/Install-Antigravity.ps1 +26 -3
- package/scripts/windows/Install-ClaudeCode.ps1 +25 -7
- package/scripts/windows/Install-CursorAgent.ps1 +45 -30
- package/scripts/windows/Install-Devin.ps1 +16 -47
- package/scripts/windows/Install-GitHubCli.ps1 +4 -0
- package/scripts/windows/Install-Goose.ps1 +18 -1
- package/scripts/windows/Install-Grok.ps1 +14 -1
- package/scripts/windows/Install-Junie.ps1 +32 -11
- package/scripts/windows/Install-KiroCli.ps1 +37 -13
- package/scripts/windows/Install-MetaCli.ps1 +8 -1
- package/scripts/windows/Install-Node.ps1 +6 -1
- package/scripts/windows/Setup-NodeGlobalPrefix.ps1 +10 -0
- package/scripts/windows/Test-WindowsInstallerSmoke.ps1 +2 -0
- package/scripts/windows/_HiddenProcess.ps1 +14 -3
- package/scripts/windows/_NativeInstallerSupport.ps1 +308 -0
- package/scripts/windows/_NpmCliInstaller.ps1 +35 -14
- package/scripts/windows/_PackagedUninstall.ps1 +9 -1
- package/scripts/windows/_VerifiedNpmUpdate.ps1 +25 -0
- package/build/renderer/assets/ActiveSessionPermissionChip-CAgN-tXv.js +0 -1
- package/build/renderer/assets/app-BV3UAQkR.css +0 -1
- package/build/renderer/assets/app-CVPqqfZo.js +0 -45
- package/build/renderer/assets/conversationSidebarRecentEntries-iqaLqA1n.js +0 -6
- package/build/server/app/renderer/settings/runtimeLifecycleHelpers.d.ts +0 -48
- package/build/server/app/renderer/settings/runtimeLifecycleHelpers.d.ts.map +0 -1
- package/build/server/app/renderer/settings/runtimeLifecycleHelpers.js +0 -535
- package/build/server/app/renderer/settings/runtimeLifecycleHelpers.js.map +0 -1
- package/build/server/design/components/useProviderRegistryAutoRecheck.d.ts +0 -13
- package/build/server/design/components/useProviderRegistryAutoRecheck.d.ts.map +0 -1
- package/build/server/design/components/useProviderRegistryAutoRecheck.js +0 -70
- package/build/server/design/components/useProviderRegistryAutoRecheck.js.map +0 -1
- package/build/server/products/shared/renderer/api/providerCatalogRefreshStore.d.ts +0 -19
- package/build/server/products/shared/renderer/api/providerCatalogRefreshStore.d.ts.map +0 -1
- package/build/server/products/shared/renderer/api/providerCatalogRefreshStore.js +0 -53
- package/build/server/products/shared/renderer/api/providerCatalogRefreshStore.js.map +0 -1
- package/build/server/products/shared/renderer/api/providers.d.ts +0 -17
- package/build/server/products/shared/renderer/api/providers.d.ts.map +0 -1
- package/build/server/products/shared/renderer/api/providers.js +0 -50
- package/build/server/products/shared/renderer/api/providers.js.map +0 -1
|
@@ -4,6 +4,7 @@ if [ -n "${CATS_PLATFORM_UNIX_PROVIDER_COMMON_SH:-}" ]; then
|
|
|
4
4
|
return 0 2>/dev/null || exit 0
|
|
5
5
|
fi
|
|
6
6
|
readonly CATS_PLATFORM_UNIX_PROVIDER_COMMON_SH=1
|
|
7
|
+
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/provider-version-common.sh"
|
|
7
8
|
|
|
8
9
|
json_escape() {
|
|
9
10
|
local value="$1"
|
|
@@ -343,7 +344,7 @@ run_downloaded_shell_installer() {
|
|
|
343
344
|
local installer_path status=0
|
|
344
345
|
|
|
345
346
|
installer_path="$(mktemp)"
|
|
346
|
-
if ! curl -fsSL "$url" -o "$installer_path"; then
|
|
347
|
+
if ! curl -fsSL --connect-timeout 10 --max-time 60 "$url" -o "$installer_path"; then
|
|
347
348
|
rm -f "$installer_path"
|
|
348
349
|
printf 'Failed to download the installer from %s\n' "$url" >&2
|
|
349
350
|
return 1
|
|
@@ -411,26 +412,8 @@ run_remote_pipe_installer() {
|
|
|
411
412
|
url="$(provider_install_url "$provider")"
|
|
412
413
|
|
|
413
414
|
case "$provider" in
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
;;
|
|
417
|
-
goose)
|
|
418
|
-
curl -fsSL "$url" | env CONFIGURE=false bash
|
|
419
|
-
;;
|
|
420
|
-
muse)
|
|
421
|
-
# Download first, then run: with `curl ... | bash` a failed download still
|
|
422
|
-
# exits 0, because bash reads empty input and succeeds.
|
|
423
|
-
run_downloaded_shell_installer "$url"
|
|
424
|
-
;;
|
|
425
|
-
cursor)
|
|
426
|
-
curl "$url" -fsSL | bash
|
|
427
|
-
;;
|
|
428
|
-
claude|junie)
|
|
429
|
-
curl -fsSL "$url" | bash
|
|
430
|
-
;;
|
|
431
|
-
*)
|
|
432
|
-
return 1
|
|
433
|
-
;;
|
|
415
|
+
goose) CONFIGURE=false run_downloaded_shell_installer "$url" ;;
|
|
416
|
+
*) run_downloaded_shell_installer "$url" ;;
|
|
434
417
|
esac
|
|
435
418
|
}
|
|
436
419
|
|
|
@@ -457,20 +440,14 @@ run_kiro_installer() {
|
|
|
457
440
|
local installer_path
|
|
458
441
|
|
|
459
442
|
installer_path="$(mktemp)"
|
|
460
|
-
curl -fsSL "$(provider_install_url kiro)" -o "$installer_path"
|
|
443
|
+
curl -fsSL --connect-timeout 10 --max-time 60 "$(provider_install_url kiro)" -o "$installer_path" || { rm -f "$installer_path"; return 1; }
|
|
461
444
|
chmod +x "$installer_path"
|
|
462
445
|
|
|
463
|
-
if [ "$mode" = 'reinstall' ]; then
|
|
464
|
-
rm -f "$HOME/.local/bin/kiro-cli" "$HOME/.local/bin/kiro-cli-chat" "$HOME/.local/bin/kiro-cli-term"
|
|
465
|
-
if [ "$platform" = 'macos' ]; then
|
|
466
|
-
rm -rf '/Applications/Kiro CLI.app'
|
|
467
|
-
rm -f "$HOME/.local/bin/bash (kiro-cli-term)" "$HOME/.local/bin/fish (kiro-cli-term)" \
|
|
468
|
-
"$HOME/.local/bin/nu (kiro-cli-term)" "$HOME/.local/bin/zsh (kiro-cli-term)"
|
|
469
|
-
fi
|
|
470
|
-
fi
|
|
471
446
|
|
|
472
|
-
|
|
447
|
+
local install_status=0
|
|
448
|
+
bash "$installer_path" --force < /dev/null || install_status=$?
|
|
473
449
|
rm -f "$installer_path"
|
|
450
|
+
[ "$install_status" -eq 0 ] || return "$install_status"
|
|
474
451
|
|
|
475
452
|
if [ "$platform" = 'macos' ]; then
|
|
476
453
|
ensure_kiro_cli_symlink_macos
|
|
@@ -485,15 +462,17 @@ run_provider_install_action() {
|
|
|
485
462
|
|
|
486
463
|
case "$provider" in
|
|
487
464
|
antigravity)
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
rm -f "$
|
|
493
|
-
run_remote_pipe_installer "$provider"
|
|
494
|
-
else
|
|
495
|
-
run_remote_pipe_installer "$provider"
|
|
465
|
+
local backup='' result=0 destination="$HOME/.local/bin/agy"
|
|
466
|
+
if { [ "$action" = upgrade ] || [ "$action" = force ]; } && [ -f "$destination" ] && [ ! -L "$destination" ]; then
|
|
467
|
+
backup="$(mktemp)" || return 1
|
|
468
|
+
cp -p "$destination" "$backup" || { rm -f "$backup"; return 1; }
|
|
469
|
+
rm -f "$destination" || { rm -f "$backup"; return 1; }
|
|
496
470
|
fi
|
|
471
|
+
run_remote_pipe_installer "$provider" || result=$?
|
|
472
|
+
[ -x "$destination" ] || result=1
|
|
473
|
+
if [ "$result" -ne 0 ] && [ -n "$backup" ]; then cp -p "$backup" "$destination" || true; fi
|
|
474
|
+
[ -z "$backup" ] || rm -f "$backup"
|
|
475
|
+
return "$result"
|
|
497
476
|
;;
|
|
498
477
|
grok)
|
|
499
478
|
run_remote_pipe_installer "$provider"
|
|
@@ -508,7 +487,7 @@ run_provider_install_action() {
|
|
|
508
487
|
;;
|
|
509
488
|
claude)
|
|
510
489
|
if [ "$action" = 'upgrade' ] && current_command="$(detect_provider_command "$platform" "$provider")"; then
|
|
511
|
-
"$current_command" update
|
|
490
|
+
"$current_command" update
|
|
512
491
|
else
|
|
513
492
|
run_remote_pipe_installer "$provider"
|
|
514
493
|
fi
|
|
@@ -986,76 +965,72 @@ run_native_provider_installer() {
|
|
|
986
965
|
return 0
|
|
987
966
|
fi
|
|
988
967
|
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
968
|
+
local before_version="$detected_version" latest='' version_state=unknown
|
|
969
|
+
local install_status=0 attempted=true final_installed=false observed_change=unchanged
|
|
970
|
+
if [ "$upgrade" = true ] && [ "$force" = false ] && [ "$initial_installed" = true ]; then
|
|
971
|
+
latest="$(cats_native_latest_version "$provider")"
|
|
972
|
+
version_state="$(cats_native_version_state "$provider" "$detected_version" "$latest")"
|
|
973
|
+
if [ "$version_state" = current ]; then
|
|
974
|
+
attempted=false
|
|
975
|
+
planned_actions=()
|
|
976
|
+
elif [ -z "$latest" ] && [ "$provider" != claude ] && [ "$provider" != muse ]; then
|
|
977
|
+
warnings+=('Could not compare the published version; the official installer will verify the update.')
|
|
978
|
+
fi
|
|
996
979
|
fi
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
980
|
+
if [ "$attempted" = true ]; then
|
|
981
|
+
printf 'Installing %s...\n' "$display_name" >&2
|
|
982
|
+
if [ "$force" = true ]; then
|
|
983
|
+
run_provider_install_action "$platform" "$provider" force || install_status=$?
|
|
984
|
+
elif [ "$upgrade" = true ]; then
|
|
985
|
+
run_provider_install_action "$platform" "$provider" upgrade || install_status=$?
|
|
986
|
+
else
|
|
987
|
+
run_provider_install_action "$platform" "$provider" install || install_status=$?
|
|
988
|
+
fi
|
|
989
|
+
fi
|
|
990
|
+
hash -r
|
|
991
|
+
if [ "$install_status" -eq 0 ]; then
|
|
992
|
+
ensure_provider_bin_path_export "$shell_rc" "$provider"
|
|
993
|
+
ensure_provider_alias "$shell_rc" "$provider"
|
|
994
|
+
fi
|
|
995
|
+
for attempt in 1 2 3; do
|
|
1003
996
|
if command_path="$(detect_provider_command "$platform" "$provider")"; then
|
|
997
|
+
final_installed=true
|
|
1004
998
|
detected_version="$(provider_version_line "$command_path" "$provider")"
|
|
1005
|
-
|
|
1006
|
-
warnings=("Reload your shell if ${display_name} is not visible yet: source ${shell_rc}")
|
|
1007
|
-
printf '{'
|
|
1008
|
-
printf '"helper":"%s-%s-native-installer",' "$platform" "$provider"
|
|
1009
|
-
printf '"mode":"%s",' "$execution_mode"
|
|
1010
|
-
printf '"status":"ready",'
|
|
1011
|
-
printf '"installed":true,'
|
|
1012
|
-
printf '"commandPath":"%s",' "$(json_escape "$command_path")"
|
|
1013
|
-
printf '"detectedVersion":"%s",' "$(json_escape "$detected_version")"
|
|
1014
|
-
printf '"plannedActions":'
|
|
1015
|
-
json_string_array "${planned_actions[@]}"
|
|
1016
|
-
printf ','
|
|
1017
|
-
printf '"appliedChanges":'
|
|
1018
|
-
json_string_array "${applied_changes[@]}"
|
|
1019
|
-
printf ','
|
|
1020
|
-
printf '"warnings":'
|
|
1021
|
-
json_string_array "${warnings[@]}"
|
|
1022
|
-
printf ','
|
|
1023
|
-
printf '"manualSteps":'
|
|
1024
|
-
json_string_array "$(provider_manual_steps "$provider")"
|
|
1025
|
-
printf ','
|
|
1026
|
-
printf '"interruptions":[]'
|
|
1027
|
-
printf '}\n'
|
|
1028
|
-
else
|
|
1029
|
-
printf '%s ready: %s\n' "$display_name" "$detected_version"
|
|
1030
|
-
printf 'Reload your shell if %s is not visible yet: source %s\n' "$display_name" "$shell_rc"
|
|
1031
|
-
fi
|
|
1032
|
-
return 0
|
|
999
|
+
break
|
|
1033
1000
|
fi
|
|
1034
|
-
|
|
1001
|
+
[ "$install_status" -eq 0 ] && [ "$attempted" = true ] || break
|
|
1035
1002
|
sleep 2
|
|
1036
|
-
attempt=$((attempt + 1))
|
|
1037
1003
|
done
|
|
1038
|
-
|
|
1039
|
-
if [ "$
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
printf ','
|
|
1053
|
-
printf '"warnings":[],'
|
|
1054
|
-
printf '"manualSteps":[],'
|
|
1055
|
-
printf '"interruptions":[]'
|
|
1056
|
-
printf '}\n'
|
|
1057
|
-
return 1
|
|
1004
|
+
local final_status=ready
|
|
1005
|
+
if [ "$install_status" -ne 0 ] || [ "$final_installed" = false ]; then
|
|
1006
|
+
final_status=failed
|
|
1007
|
+
observed_change=failed
|
|
1008
|
+
warnings+=("Installer or verification failed (exit $install_status); any previous installation is shown separately.")
|
|
1009
|
+
elif [ "$attempted" = false ]; then observed_change=unchanged
|
|
1010
|
+
elif [ "$initial_installed" = false ]; then observed_change=installed
|
|
1011
|
+
elif [ -n "$before_version" ] && [ -n "$detected_version" ] && [ "$before_version" != "$detected_version" ]; then
|
|
1012
|
+
case "$(cats_version_compare "$(cats_native_version_token "$provider" "$detected_version")" "$(cats_native_version_token "$provider" "$before_version")")" in
|
|
1013
|
+
1) observed_change=upgraded ;; -1) observed_change=downgraded ;; *) observed_change=version_changed ;;
|
|
1014
|
+
esac
|
|
1015
|
+
else observed_change=unchanged; fi
|
|
1016
|
+
if [ "$final_status" = ready ] && { [ "$upgrade" = true ] || [ "$force" = true ]; }; then
|
|
1017
|
+
cats_cleanup_native_versions "$provider" "$detected_version" || true
|
|
1058
1018
|
fi
|
|
1059
|
-
|
|
1060
|
-
|
|
1019
|
+
case "$observed_change" in
|
|
1020
|
+
installed|upgraded|downgraded|version_changed) applied_changes=("${observed_change}_${provider}_installation") ;;
|
|
1021
|
+
esac
|
|
1022
|
+
if [ "$emit_json" = true ]; then
|
|
1023
|
+
printf '{"helper":"%s-%s-native-installer","mode":"%s","status":"%s",' "$platform" "$provider" "$execution_mode" "$final_status"
|
|
1024
|
+
printf '"installed":%s,"commandPath":"%s","detectedVersion":"%s",' "$final_installed" "$(json_escape "$command_path")" "$(json_escape "$detected_version")"
|
|
1025
|
+
printf '"previousVersion":"%s","observedChange":"%s",' "$(json_escape "$before_version")" "$observed_change"
|
|
1026
|
+
printf '"summary":"%s: %s -> %s",' "$observed_change" "$(json_escape "$before_version")" "$(json_escape "$detected_version")"
|
|
1027
|
+
printf '"plannedActions":'; json_string_array "${planned_actions[@]}"
|
|
1028
|
+
printf ',"appliedChanges":'; json_string_array "${applied_changes[@]}"
|
|
1029
|
+
printf ',"warnings":'; json_string_array "${warnings[@]}"
|
|
1030
|
+
printf ',"manualSteps":'; json_string_array "$(provider_manual_steps "$provider")"
|
|
1031
|
+
printf ',"interruptions":[]}\n'
|
|
1032
|
+
else
|
|
1033
|
+
printf '%s %s: %s -> %s\n' "$display_name" "$observed_change" "$before_version" "$detected_version"
|
|
1034
|
+
fi
|
|
1035
|
+
[ "$final_status" = ready ]
|
|
1061
1036
|
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Source this file for passive native version comparison and bounded vendor queries.
|
|
3
|
+
# Usage: source provider-version-common.sh; cats_native_latest_version <provider>
|
|
4
|
+
# Adapted from environment-bootstrap shared/posix/upstream-version.sh at 752dc13.
|
|
5
|
+
# Queries return an empty value on failure; check-only mode never invokes them.
|
|
6
|
+
cats_version_token() {
|
|
7
|
+
printf '%s' "$1" | tr -d '\r' | grep -oE '[0-9]+(\.[0-9]+)+(-[0-9A-Za-z]+(\.[0-9A-Za-z]+)*|\.[A-Za-z][0-9A-Za-z]*(\.[0-9]+)*)?' | head -n 1 || true
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
# cats_version_compare <a> <b>
|
|
11
|
+
# 只比數字段、補滿四段:印 -1(a 較舊)、0、1(a 較新);任一邊解析不出版本印空字串。
|
|
12
|
+
# 空字串要當成「無法比較、交回原本流程」,不能當成落後,否則查不到版本時每次都會重裝。
|
|
13
|
+
cats_version_compare() {
|
|
14
|
+
local a b i x y
|
|
15
|
+
a="$(printf '%s' "$1" | tr -d '\r' | grep -oE '[0-9]+(\.[0-9]+)*' | head -n 1 || true)"
|
|
16
|
+
b="$(printf '%s' "$2" | tr -d '\r' | grep -oE '[0-9]+(\.[0-9]+)*' | head -n 1 || true)"
|
|
17
|
+
if [ -z "$a" ] || [ -z "$b" ]; then
|
|
18
|
+
printf ''
|
|
19
|
+
return 0
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
i=1
|
|
23
|
+
while [ "$i" -le 4 ]; do
|
|
24
|
+
x="$(printf '%s' "$a" | awk -F. -v n="$i" '{print $n}')"
|
|
25
|
+
y="$(printf '%s' "$b" | awk -F. -v n="$i" '{print $n}')"
|
|
26
|
+
[ -n "$x" ] || x=0
|
|
27
|
+
[ -n "$y" ] || y=0
|
|
28
|
+
if [ "$((10#$x))" -lt "$((10#$y))" ]; then printf -- '-1'; return 0; fi
|
|
29
|
+
if [ "$((10#$x))" -gt "$((10#$y))" ]; then printf '1'; return 0; fi
|
|
30
|
+
i=$((i + 1))
|
|
31
|
+
done
|
|
32
|
+
printf '0'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# _cats_json_string_field <field> :從 stdin 的 JSON 文字撈第一個 "field":"value" 的 value
|
|
36
|
+
_cats_json_string_field() {
|
|
37
|
+
grep -oE "\"$1\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" | head -n 1 | sed -E 's/.*"([^"]*)"$/\1/'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# cats_github_latest_release <owner/repo>
|
|
41
|
+
# GitHub Releases 的最新穩定版 tag(去掉開頭的 v);失敗印空。
|
|
42
|
+
cats_github_latest_release() {
|
|
43
|
+
local json
|
|
44
|
+
json="$(curl -fsSL --connect-timeout 5 --max-time 20 -H 'Accept: application/vnd.github+json' "https://api.github.com/repos/$1/releases/latest" 2>/dev/null)" || return 0
|
|
45
|
+
printf '%s' "$json" | _cats_json_string_field tag_name | sed 's/^v//' || true
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# cats_antigravity_latest_version [已下載的官方 install.sh]
|
|
49
|
+
# 官方腳本讀的是 $DOWNLOAD_BASE_URL/manifests/<platform>.json 的 version。
|
|
50
|
+
# 傳入抓下來的腳本可以順便從裡面撈 base URL,官方搬家時就不必改這裡;撈不到用寫死的。
|
|
51
|
+
# platform 的算法照抄官方(darwin_arm64 / linux_amd64 / linux_amd64_musl …)。
|
|
52
|
+
cats_antigravity_latest_version() {
|
|
53
|
+
local base='https://antigravity-cli-auto-updater-974169037036.us-central1.run.app'
|
|
54
|
+
local found os arch platform
|
|
55
|
+
|
|
56
|
+
if [ -n "${1:-}" ] && [ -r "$1" ]; then
|
|
57
|
+
found="$(grep -oE 'DOWNLOAD_BASE_URL="https://[^"]+"' "$1" | head -n 1 | sed -E 's/^DOWNLOAD_BASE_URL="(.*)"$/\1/')"
|
|
58
|
+
[ -n "$found" ] && base="$found"
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
case "$(uname -s)" in
|
|
62
|
+
Darwin) os=darwin ;;
|
|
63
|
+
Linux) os=linux ;;
|
|
64
|
+
*) return 0 ;;
|
|
65
|
+
esac
|
|
66
|
+
case "$(uname -m)" in
|
|
67
|
+
x86_64|amd64) arch=amd64 ;;
|
|
68
|
+
arm64|aarch64) arch=arm64 ;;
|
|
69
|
+
*) return 0 ;;
|
|
70
|
+
esac
|
|
71
|
+
if [ "$os" = linux ] && { [ -f /lib/libc.musl-x86_64.so.1 ] || [ -f /lib/libc.musl-aarch64.so.1 ] || ldd /bin/ls 2>&1 | grep -q musl; }; then
|
|
72
|
+
platform="linux_${arch}_musl"
|
|
73
|
+
else
|
|
74
|
+
platform="${os}_${arch}"
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
curl -fsSL --connect-timeout 5 --max-time 20 "$base/manifests/$platform.json" 2>/dev/null | _cats_json_string_field version || true
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# cats_cursor_agent_latest_version <已下載的官方 install 腳本>
|
|
81
|
+
# 官方 https://cursor.com/install 是支寫死版本的腳本,目錄名就是版本
|
|
82
|
+
# (…/versions/2026.09.10-fd3934a)。版本是「日期-commit」,cats_version_compare 只比得到
|
|
83
|
+
# 日期,同日不同 commit 由呼叫端用字串相等另判。
|
|
84
|
+
cats_cursor_agent_latest_version() {
|
|
85
|
+
[ -n "${1:-}" ] && [ -r "$1" ] || return 0
|
|
86
|
+
grep -oE 'versions/[0-9]{4}\.[0-9]{2}\.[0-9]{2}-[0-9A-Za-z]+' "$1" | head -n 1 | sed 's#^versions/##' || true
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# cats_junie_latest_build
|
|
90
|
+
# 官方 install.sh 讀 GitHub raw 的 update-info.jsonl:一行一個 build,version 是 build 號
|
|
91
|
+
# (3110.7,也是 versions/ 底下的目錄名)、marketing 才是 26.9.7、platform 是
|
|
92
|
+
# linux-amd64 / macos-aarch64 這種。印本平台最大的 build 號;失敗印空。
|
|
93
|
+
cats_junie_latest_build() {
|
|
94
|
+
local os arch platform jsonl line v best=''
|
|
95
|
+
|
|
96
|
+
case "$(uname -s)" in
|
|
97
|
+
Darwin) os=macos ;;
|
|
98
|
+
Linux) os=linux ;;
|
|
99
|
+
*) return 0 ;;
|
|
100
|
+
esac
|
|
101
|
+
case "$(uname -m)" in
|
|
102
|
+
x86_64|amd64) arch=amd64 ;;
|
|
103
|
+
arm64|aarch64) arch=aarch64 ;;
|
|
104
|
+
*) return 0 ;;
|
|
105
|
+
esac
|
|
106
|
+
platform="${os}-${arch}"
|
|
107
|
+
|
|
108
|
+
jsonl="$(curl -fsSL --connect-timeout 5 --max-time 20 'https://raw.githubusercontent.com/jetbrains-junie/junie/main/update-info.jsonl' 2>/dev/null)" || return 0
|
|
109
|
+
|
|
110
|
+
while IFS= read -r line; do
|
|
111
|
+
case "$line" in
|
|
112
|
+
*"\"platform\":\"$platform\""*) ;;
|
|
113
|
+
*) continue ;;
|
|
114
|
+
esac
|
|
115
|
+
v="$(printf '%s' "$line" | _cats_json_string_field version || true)"
|
|
116
|
+
[ -n "$v" ] || continue
|
|
117
|
+
if [ -z "$best" ] || [ "$(cats_version_compare "$v" "$best")" = "1" ]; then
|
|
118
|
+
best="$v"
|
|
119
|
+
fi
|
|
120
|
+
done <<< "$jsonl"
|
|
121
|
+
|
|
122
|
+
printf '%s' "$best"
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
# cats_kiro_latest_version
|
|
126
|
+
# Kiro 的官方 installer 讀 stable/latest/manifest.json(Windows 版 Install-KiroCLI.ps1
|
|
127
|
+
# 用的是同一份),欄位 version。
|
|
128
|
+
cats_kiro_latest_version() {
|
|
129
|
+
curl -fsSL --connect-timeout 5 --max-time 20 'https://prod.download.cli.kiro.dev/stable/latest/manifest.json' 2>/dev/null | _cats_json_string_field version || true
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
# cats_devin_latest_version
|
|
133
|
+
# Devin 的官方 install.sh 與 Windows 版 setup.ps1 讀的都是 cli/current/manifest.json,欄位
|
|
134
|
+
# version(3000.10.27)。官方腳本同版雖不重抓,POSIX 版仍會重建兩個符號連結、Windows 版更會
|
|
135
|
+
# 無條件重寫 180 MB 的 devin.exe;先問這裡,同版就完全不動。
|
|
136
|
+
cats_devin_latest_version() {
|
|
137
|
+
curl -fsSL --connect-timeout 5 --max-time 20 'https://static.devin.ai/cli/current/manifest.json' 2>/dev/null | _cats_json_string_field version || true
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
# cats_grok_latest_version [channel]
|
|
141
|
+
# Grok 的官方 install.sh(與 Windows 的 install.ps1)決定要下載哪一版,靠的只是一個純文字端點:
|
|
142
|
+
# https://x.ai/cli/<channel>(Cloudflare 前端)不通就退到 GCS 上的同名檔案,內容就是版本號
|
|
143
|
+
# (1.0.30)。這裡照抄同一套順序;channel 預設跟官方一樣吃 GROK_CHANNEL(stable)。
|
|
144
|
+
# 三平台都問這裡,刻意不用 `grok update --check --json`:那要執行 grok 本體去連 x.ai 做 TLS
|
|
145
|
+
# 交握,而 grok 的 TLS 實作用到 SHA-512 硬體指令(sha512su0),沒有這個擴充的 aarch64
|
|
146
|
+
# (Raspberry Pi 4/5 的 Cortex-A72/A76)會當場 SIGILL、輸出全空 —— 見 CLAUDE.md Known Gotchas。
|
|
147
|
+
# 這個端點不必執行任何工具,問到的也正是安裝器接下來會抓的版本。失敗印空。
|
|
148
|
+
cats_grok_latest_version() {
|
|
149
|
+
local channel="${1:-${GROK_CHANNEL:-stable}}" url v
|
|
150
|
+
for url in "https://x.ai/cli/${channel}" "https://storage.googleapis.com/grok-build-public-artifacts/cli/${channel}"; do
|
|
151
|
+
v="$(curl -fsSL --connect-timeout 5 --max-time 20 "$url" 2>/dev/null | tr -d '\r' | head -n 1 | tr -d '[:space:]' || true)"
|
|
152
|
+
if printf '%s' "$v" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9._]+)?$'; then
|
|
153
|
+
printf '%s' "$v"
|
|
154
|
+
return 0
|
|
155
|
+
fi
|
|
156
|
+
done
|
|
157
|
+
printf ''
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
cats_native_latest_version() {
|
|
162
|
+
local script
|
|
163
|
+
case "$1" in
|
|
164
|
+
antigravity) cats_antigravity_latest_version ;;
|
|
165
|
+
cursor)
|
|
166
|
+
script="$(curl -fsSL --connect-timeout 5 --max-time 20 https://cursor.com/install 2>/dev/null)" || return 0
|
|
167
|
+
printf '%s' "$script" | grep -oE 'versions/[0-9]{4}\.[0-9]{2}\.[0-9]{2}-[0-9A-Za-z]+' | head -n 1 | sed 's#^versions/##' || true
|
|
168
|
+
;;
|
|
169
|
+
goose) cats_github_latest_release aaif-goose/goose ;;
|
|
170
|
+
junie) cats_junie_latest_build ;;
|
|
171
|
+
kiro) cats_kiro_latest_version ;;
|
|
172
|
+
devin) cats_devin_latest_version ;;
|
|
173
|
+
grok) cats_grok_latest_version ;;
|
|
174
|
+
*) return 0 ;;
|
|
175
|
+
esac
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
cats_native_version_token() {
|
|
179
|
+
if [ "$1" = junie ]; then
|
|
180
|
+
printf '%s' "$2" | sed -nE 's/.*\(([0-9]+(\.[0-9]+)+)\).*/\1/p' | head -n 1 || true
|
|
181
|
+
else
|
|
182
|
+
cats_version_token "$2"
|
|
183
|
+
fi
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
# Print current/older/unknown; Cursor same-day hashes are distinct releases.
|
|
187
|
+
cats_native_version_state() {
|
|
188
|
+
local current latest comparison
|
|
189
|
+
current="$(cats_native_version_token "$1" "$2")"
|
|
190
|
+
latest="$3"
|
|
191
|
+
[ -n "$current" ] && [ -n "$latest" ] || { printf unknown; return 0; }
|
|
192
|
+
comparison="$(cats_version_compare "$current" "$latest")"
|
|
193
|
+
if [ "$comparison" = 1 ] || { [ "$comparison" = 0 ] && { [ "$1" != cursor ] || [ "$current" = "$latest" ]; }; }; then
|
|
194
|
+
printf current
|
|
195
|
+
elif [ -n "$comparison" ]; then printf older
|
|
196
|
+
else printf unknown; fi
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
# Delete only older numeric version directories in a known installer-owned tree.
|
|
200
|
+
# Current/pending/newer builds, symlinks and custom locations outside HOME remain.
|
|
201
|
+
cats_cleanup_native_versions() {
|
|
202
|
+
local provider="$1" version="$2" root='' data='' keep='' actual='' directory='' name='' ancestor=''
|
|
203
|
+
keep="$(cats_native_version_token "$provider" "$version")"
|
|
204
|
+
[ -n "$keep" ] || return 0
|
|
205
|
+
case "$provider" in
|
|
206
|
+
cursor)
|
|
207
|
+
root="$HOME/.local/share/cursor-agent/versions"
|
|
208
|
+
[ -L "$HOME/.local/bin/cursor-agent" ] || return 0
|
|
209
|
+
actual="$(readlink "$HOME/.local/bin/cursor-agent")" || return 0
|
|
210
|
+
[ "$(basename "$(dirname "$actual")")" = "$keep" ] || return 0
|
|
211
|
+
;;
|
|
212
|
+
devin)
|
|
213
|
+
root="${XDG_DATA_HOME:-$HOME/.local/share}/devin/cli/_versions"
|
|
214
|
+
[ -L "$root/current" ] || return 0
|
|
215
|
+
actual="$(readlink "$root/current")" || return 0
|
|
216
|
+
[ "$(basename "$actual")" = "$keep" ] || return 0
|
|
217
|
+
;;
|
|
218
|
+
junie)
|
|
219
|
+
data="${JUNIE_DATA_DIR:-$HOME/.local/share/junie}"
|
|
220
|
+
root="$data/versions"
|
|
221
|
+
[ ! -e "$data/updates/pending-update.json" ] && [ -L "$data/current" ] || return 0
|
|
222
|
+
actual="$(readlink "$data/current")" || return 0
|
|
223
|
+
[ "$(basename "$actual")" = "$keep" ] || return 0
|
|
224
|
+
;;
|
|
225
|
+
*) return 0 ;;
|
|
226
|
+
esac
|
|
227
|
+
case "$root" in "$HOME"/*) ;; *) return 0 ;; esac
|
|
228
|
+
[ -d "$root" ] || return 0
|
|
229
|
+
ancestor="$root"
|
|
230
|
+
while [ "$ancestor" != / ] && [ "$ancestor" != . ]; do
|
|
231
|
+
[ ! -L "$ancestor" ] || return 0
|
|
232
|
+
ancestor="$(dirname "$ancestor")"
|
|
233
|
+
done
|
|
234
|
+
local canonical_home
|
|
235
|
+
canonical_home="$(cd -P -- "$HOME" && pwd -P)" || return 0
|
|
236
|
+
root="$(cd -P -- "$root" && pwd -P)" || return 0
|
|
237
|
+
case "$root" in "$canonical_home"/*) ;; *) return 0 ;; esac
|
|
238
|
+
for directory in "$root"/*; do
|
|
239
|
+
[ -d "$directory" ] && [ ! -L "$directory" ] || continue
|
|
240
|
+
name="$(basename "$directory")"
|
|
241
|
+
printf '%s' "$name" | grep -qE '^[0-9]+(\.[0-9]+)+(-[0-9A-Za-z]+)?$' || continue
|
|
242
|
+
[ "$(cats_version_compare "$name" "$keep")" = -1 ] || continue
|
|
243
|
+
# Skip directory trees with links rather than recurse through an unknown layout.
|
|
244
|
+
[ -z "$(find "$directory" -type l -print 2>/dev/null)" ] || continue
|
|
245
|
+
rm -rf -- "$directory" || printf 'Could not remove old %s build %s.\n' "$provider" "$name" >&2
|
|
246
|
+
done
|
|
247
|
+
}
|
|
@@ -66,6 +66,8 @@ assert_file "${RESOURCES_ROOT}/desktop/setup-assets/linux/install-goose.sh" 'bun
|
|
|
66
66
|
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/linux/install-junie.sh" 'bundled Linux Junie installer helper'
|
|
67
67
|
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/linux/install-kiro-cli.sh" 'bundled Linux Kiro installer helper'
|
|
68
68
|
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/linux/check-installation.sh" 'bundled Linux readiness audit helper'
|
|
69
|
+
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/linux/provider-version-common.sh" 'bundled native version library'
|
|
70
|
+
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/linux/verified-npm-update.sh" 'bundled npm verification library'
|
|
69
71
|
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/linux/provider-cli-common.sh" 'bundled Linux provider helper library'
|
|
70
72
|
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/linux/node-cli-common.sh" 'bundled Linux npm helper library'
|
|
71
73
|
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/manifest.json" 'bundled setup-assets manifest'
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Usage: source verified-npm-update.sh; cats_upgrade_npm
|
|
3
|
+
# Explicit npm upgrade only. Adapted from environment-bootstrap 4690075.
|
|
4
|
+
# Preserve the current prefix (including nvm), enforce engines, verify command and package.
|
|
5
|
+
cats_upgrade_npm() {
|
|
6
|
+
local current latest installed root
|
|
7
|
+
current="$(npm --version)" || { printf 'Could not read npm version.\n' >&2; return 1; }
|
|
8
|
+
latest="$(npm view npm@latest version --fetch-retries=0 --fetch-timeout=10000 --loglevel=error)" || { printf 'npm version query failed.\n' >&2; return 1; }
|
|
9
|
+
[[ "$latest" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { printf 'Invalid npm version metadata.\n' >&2; return 1; }
|
|
10
|
+
[ "$current" != "$latest" ] || return 0
|
|
11
|
+
[ "$(cats_version_compare "$current" "$latest")" != 1 ] || return 0
|
|
12
|
+
npm install -g "npm@$latest" --engine-strict --fetch-retries=0 --fetch-timeout=30000 || return 1
|
|
13
|
+
hash -r
|
|
14
|
+
installed="$(npm --version)" && root="$(npm root -g)" || return 1
|
|
15
|
+
[ "$installed" = "$latest" ] && node -e '
|
|
16
|
+
const path = require("path");
|
|
17
|
+
const pkg = require(path.join(process.argv[1], "npm", "package.json"));
|
|
18
|
+
process.exit(pkg.version === process.argv[2] ? 0 : 1);
|
|
19
|
+
' "$root" "$latest" || { printf 'npm verification failed. Check PATH and prefix.\n' >&2; return 1; }
|
|
20
|
+
}
|
|
@@ -60,6 +60,11 @@ declare -a applied_changes=()
|
|
|
60
60
|
declare -a warnings=()
|
|
61
61
|
declare -a manual_steps=()
|
|
62
62
|
|
|
63
|
+
# A Desktop-launched helper may inherit PATH from before gh was installed.
|
|
64
|
+
# Include our fallback destination and the supported Homebrew locations in this
|
|
65
|
+
# process only; check mode must not edit the user's shell profile.
|
|
66
|
+
export PATH="$HOME/.local/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"
|
|
67
|
+
|
|
63
68
|
resolve_gh_path() {
|
|
64
69
|
command -v gh 2>/dev/null || true
|
|
65
70
|
}
|
|
@@ -90,7 +90,7 @@ is_node_installed() {
|
|
|
90
90
|
if [ "$skip_node_probe" = 'true' ]; then
|
|
91
91
|
return 1
|
|
92
92
|
fi
|
|
93
|
-
command -v node >/dev/null 2>&1
|
|
93
|
+
command -v node >/dev/null 2>&1 && command -v npm >/dev/null 2>&1
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
json_array_from_lines() {
|
|
@@ -149,6 +149,12 @@ JSON
|
|
|
149
149
|
exit "$exit_code"
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
# Desktop's environment may predate nvm installation. Load it before read-only
|
|
153
|
+
# detection too; a bundled or standalone node without npm is not this substrate.
|
|
154
|
+
if [ "$install_state" = 'auto' ] && [ "$skip_node_probe" = 'false' ]; then
|
|
155
|
+
load_nvm
|
|
156
|
+
fi
|
|
157
|
+
|
|
152
158
|
# Mode: check
|
|
153
159
|
if [ "$mode" = 'check' ]; then
|
|
154
160
|
if is_node_installed; then
|
|
@@ -214,10 +220,10 @@ case "$mode" in
|
|
|
214
220
|
;;
|
|
215
221
|
esac
|
|
216
222
|
|
|
217
|
-
if command -v node >/dev/null 2>&1; then
|
|
223
|
+
if command -v node >/dev/null 2>&1 && command -v npm >/dev/null 2>&1; then
|
|
218
224
|
emit_result 'ready' 'true' 0
|
|
219
225
|
else
|
|
220
|
-
warnings+=('Node
|
|
226
|
+
warnings+=('Node.js or npm is still missing after install.')
|
|
221
227
|
manual_steps+=('Open a new terminal so PATH picks up the nvm-managed node binary.')
|
|
222
228
|
emit_result 'failed' 'false' 1
|
|
223
229
|
fi
|