@cats-inc/cats-platform 0.1.7 → 0.1.9
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 +8 -8
- package/build/desktop/bootstrapPage.d.ts.map +1 -1
- package/build/desktop/bootstrapPage.js +5 -1
- package/build/desktop/bootstrapPage.js.map +1 -1
- package/build/desktop/cliInventoryProbe.d.ts.map +1 -1
- package/build/desktop/cliInventoryProbe.js +12 -0
- package/build/desktop/cliInventoryProbe.js.map +1 -1
- package/build/desktop/contracts.d.ts +1 -1
- package/build/desktop/contracts.d.ts.map +1 -1
- package/build/desktop/contracts.js +4 -0
- package/build/desktop/contracts.js.map +1 -1
- package/build/desktop/main.js +41 -9
- package/build/desktop/main.js.map +1 -1
- package/build/desktop/packaging.d.ts.map +1 -1
- package/build/desktop/packaging.js +62 -0
- package/build/desktop/packaging.js.map +1 -1
- package/build/desktop/setupAssets.d.ts.map +1 -1
- package/build/desktop/setupAssets.js +134 -0
- package/build/desktop/setupAssets.js.map +1 -1
- package/build/desktop/updateInstallHandoff.d.ts +14 -0
- package/build/desktop/updateInstallHandoff.d.ts.map +1 -1
- package/build/desktop/updateInstallHandoff.js +23 -0
- package/build/desktop/updateInstallHandoff.js.map +1 -1
- package/build/desktop/updateManager.d.ts.map +1 -1
- package/build/desktop/updateManager.js +8 -0
- package/build/desktop/updateManager.js.map +1 -1
- package/build/desktop/updaterAdapter.d.ts +16 -1
- package/build/desktop/updaterAdapter.d.ts.map +1 -1
- package/build/desktop/updaterAdapter.js +49 -2
- package/build/desktop/updaterAdapter.js.map +1 -1
- package/build/renderer/assets/{ActiveSessionPermissionChip-BRMLwkvf.js → ActiveSessionPermissionChip-Dl2UOFgh.js} +1 -1
- package/build/renderer/assets/{App-BM2nzo6s.js → App-C57f4p8k.js} +1 -1
- package/build/renderer/assets/{App-CVQAwCMi.js → App-CPqGDXVi.js} +1 -1
- package/build/renderer/assets/{App-Dl5FLaR_.js → App-ChvP0G9X.js} +1 -1
- package/build/renderer/assets/{WorkspaceAppRoutes-C3DUzdbj.js → WorkspaceAppRoutes-DYg2vnjz.js} +1 -1
- package/build/renderer/assets/{app-hP5h2jAt.js → app-DVN9Ghrk.js} +3 -3
- package/build/renderer/assets/{conversationSidebarRecentEntries-B-mNvfiy.js → conversationSidebarRecentEntries-XZVCnMLw.js} +1 -1
- package/build/renderer/assets/{useDraftSessionChips-DuXIoptW.js → useDraftSessionChips-By3XXabI.js} +1 -1
- package/build/renderer/index.html +1 -1
- package/build/server/shared/providerCatalog.d.ts +2 -2
- package/build/server/shared/providerCatalog.d.ts.map +1 -1
- package/build/server/shared/providerCatalogData.d.ts +11 -1
- package/build/server/shared/providerCatalogData.d.ts.map +1 -1
- package/build/server/shared/providerCatalogData.js +8 -0
- package/build/server/shared/providerCatalogData.js.map +1 -1
- package/build/server/shared/providerCatalogInstances.d.ts.map +1 -1
- package/build/server/shared/providerCatalogInstances.js +6 -0
- package/build/server/shared/providerCatalogInstances.js.map +1 -1
- package/package.json +6 -3
- package/scripts/README.md +51 -2
- package/scripts/linux/install-aider.sh +8 -0
- package/scripts/linux/install-cline.sh +8 -0
- package/scripts/linux/install-devin.sh +8 -0
- package/scripts/linux/install-grok.sh +8 -0
- package/scripts/linux/install-pi.sh +1 -1
- package/scripts/linux/node-cli-common.sh +43 -3
- package/scripts/linux/provider-cli-common.sh +162 -24
- package/scripts/linux/test-linux-package-smoke.sh +16 -0
- package/scripts/linux/upgrade-cli-tools.sh +2 -2
- package/scripts/macos/install-aider.sh +8 -0
- package/scripts/macos/install-cline.sh +8 -0
- package/scripts/macos/install-devin.sh +8 -0
- package/scripts/macos/install-grok.sh +8 -0
- package/scripts/macos/install-pi.sh +1 -1
- package/scripts/macos/node-cli-common.sh +43 -3
- package/scripts/macos/provider-cli-common.sh +162 -24
- package/scripts/macos/test-macos-package-smoke.sh +15 -0
- package/scripts/macos/upgrade-cli-tools.sh +2 -2
- package/scripts/windows/Check-WindowsSetupReadiness.ps1 +32 -1
- package/scripts/windows/Install-Aider.ps1 +368 -0
- package/scripts/windows/Install-Cline.ps1 +39 -0
- package/scripts/windows/Install-Devin.ps1 +385 -0
- package/scripts/windows/Install-Grok.ps1 +355 -0
- package/scripts/windows/Install-Pi.ps1 +1 -1
- package/scripts/windows/Test-WindowsInstallerSmoke.ps1 +23 -0
- package/scripts/windows/_NpmCliInstaller.ps1 +41 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Install or verify the native Windows Devin CLI for Cats.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Cats-owned packaged setup wrapper for Cognition's Devin CLI. The official
|
|
7
|
+
installer places devin.exe in %LOCALAPPDATA%\devin\cli\bin and keeps
|
|
8
|
+
versions under %LOCALAPPDATA%\devin\cli, both of which uninstall removes.
|
|
9
|
+
|
|
10
|
+
The installer's final line launches the interactive devin setup wizard,
|
|
11
|
+
which packaged setup strips because it runs with no console a prompt can
|
|
12
|
+
reach. Authentication is therefore still owed after a successful install:
|
|
13
|
+
run devin auth login once and check with devin auth status.
|
|
14
|
+
#>
|
|
15
|
+
param(
|
|
16
|
+
[switch]$CheckOnly,
|
|
17
|
+
[switch]$Apply,
|
|
18
|
+
[switch]$Upgrade,
|
|
19
|
+
[switch]$Force,
|
|
20
|
+
[switch]$Uninstall,
|
|
21
|
+
[switch]$DryRun,
|
|
22
|
+
[switch]$Json,
|
|
23
|
+
[switch]$AllowAdmin,
|
|
24
|
+
[ValidateSet('auto', 'installed', 'missing')]
|
|
25
|
+
[string]$InstallState = 'auto',
|
|
26
|
+
[string]$DetectedVersion = '',
|
|
27
|
+
[switch]$SkipInstaller
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
Set-StrictMode -Version Latest
|
|
31
|
+
$ErrorActionPreference = 'Stop'
|
|
32
|
+
|
|
33
|
+
. (Join-Path $PSScriptRoot '_HiddenProcess.ps1')
|
|
34
|
+
. (Join-Path $PSScriptRoot '_PackagedUninstall.ps1')
|
|
35
|
+
|
|
36
|
+
function Write-StructuredResult {
|
|
37
|
+
param(
|
|
38
|
+
[pscustomobject]$Result,
|
|
39
|
+
[int]$ExitCode
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
if ($Json) {
|
|
43
|
+
$Result | ConvertTo-Json -Depth 10
|
|
44
|
+
} else {
|
|
45
|
+
Write-Host "Mode: $($Result.mode)"
|
|
46
|
+
Write-Host "Status: $($Result.status)"
|
|
47
|
+
Write-Host "Installed: $($Result.installed)"
|
|
48
|
+
if ($Result.detectedVersion) { Write-Host "Version: $($Result.detectedVersion)" }
|
|
49
|
+
foreach ($action in $Result.plannedActions) { Write-Host "Planned action: $action" }
|
|
50
|
+
foreach ($warning in $Result.warnings) { Write-Host "Warning: $warning" }
|
|
51
|
+
foreach ($step in $Result.manualSteps) { Write-Host "Manual step: $step" }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
exit $ExitCode
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function Resolve-DevinInstallDir {
|
|
58
|
+
return Join-Path $env:LOCALAPPDATA 'devin\cli\bin'
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function Resolve-DevinExecutablePath {
|
|
62
|
+
return Join-Path (Resolve-DevinInstallDir) 'devin.exe'
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function Refresh-UserPath {
|
|
66
|
+
$env:Path = [System.Environment]::GetEnvironmentVariable('Path', 'User') + ';' +
|
|
67
|
+
[System.Environment]::GetEnvironmentVariable('Path', 'Machine')
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function Detect-DevinInstall {
|
|
71
|
+
$exePath = Resolve-DevinExecutablePath
|
|
72
|
+
|
|
73
|
+
if ($InstallState -eq 'installed') {
|
|
74
|
+
return [pscustomobject]@{
|
|
75
|
+
installed = $true
|
|
76
|
+
commandPath = $exePath
|
|
77
|
+
detectedVersion = $DetectedVersion
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if ($InstallState -eq 'missing') {
|
|
81
|
+
return [pscustomobject]@{
|
|
82
|
+
installed = $false
|
|
83
|
+
commandPath = $exePath
|
|
84
|
+
detectedVersion = $DetectedVersion
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
Refresh-UserPath
|
|
89
|
+
$command = Get-Command devin -ErrorAction SilentlyContinue
|
|
90
|
+
$installed = $null -ne $command -or (Test-Path -LiteralPath $exePath -PathType Leaf)
|
|
91
|
+
$commandPath = if ($null -ne $command) { $command.Source } else { $exePath }
|
|
92
|
+
$commandSource = if ($null -ne $command) { $command.Source } else { '' }
|
|
93
|
+
$version = $DetectedVersion
|
|
94
|
+
$versionProbePath = Resolve-HiddenVersionProbePath `
|
|
95
|
+
-PreferredPath $commandSource `
|
|
96
|
+
-FallbackPath $exePath
|
|
97
|
+
|
|
98
|
+
if ($installed -and [string]::IsNullOrWhiteSpace($version) -and $versionProbePath) {
|
|
99
|
+
try {
|
|
100
|
+
$version = Get-HiddenCommandText -FileName $versionProbePath -ArgumentList @('--version')
|
|
101
|
+
} catch {
|
|
102
|
+
$version = ''
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return [pscustomobject]@{
|
|
107
|
+
installed = $installed
|
|
108
|
+
commandPath = $commandPath
|
|
109
|
+
detectedVersion = $version
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function Add-DevinToUserPath {
|
|
114
|
+
$installDir = Resolve-DevinInstallDir
|
|
115
|
+
$userPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
|
|
116
|
+
if ([string]::IsNullOrWhiteSpace($userPath)) {
|
|
117
|
+
[System.Environment]::SetEnvironmentVariable('Path', $installDir, 'User')
|
|
118
|
+
} elseif ($userPath -notlike "*$installDir*") {
|
|
119
|
+
[System.Environment]::SetEnvironmentVariable('Path', "$installDir;$userPath", 'User')
|
|
120
|
+
}
|
|
121
|
+
Refresh-UserPath
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function Invoke-DevinInstaller {
|
|
125
|
+
if ($SkipInstaller) {
|
|
126
|
+
return [pscustomobject]@{ skipped = $true; success = $true; exitCode = 0; stderr = '' }
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
$tempScript = [System.IO.Path]::Combine(
|
|
130
|
+
[System.IO.Path]::GetTempPath(),
|
|
131
|
+
"cats-devin-install-$([System.Guid]::NewGuid().ToString('N')).ps1"
|
|
132
|
+
)
|
|
133
|
+
$stdoutPath = "$tempScript.stdout"
|
|
134
|
+
$stderrPath = "$tempScript.stderr"
|
|
135
|
+
# Devin's setup.ps1 ends by launching the interactive `devin setup` wizard.
|
|
136
|
+
# Packaged setup runs with no console a prompt can reach, so an unstripped
|
|
137
|
+
# installer would stall the step rather than fail.
|
|
138
|
+
#
|
|
139
|
+
# Verified against https://static.devin.ai/cli/setup.ps1 on 2026-08-09: the
|
|
140
|
+
# file is 234 lines and its final line is `& $EntryExe setup`, which is also
|
|
141
|
+
# the only line in the file that invokes setup. The helper refuses to run the
|
|
142
|
+
# script when that shape does not hold rather than executing an unrecognised
|
|
143
|
+
# installer on a guess.
|
|
144
|
+
$installerSource = ''
|
|
145
|
+
try {
|
|
146
|
+
$installerSource = Invoke-RestMethod 'https://static.devin.ai/cli/setup.ps1'
|
|
147
|
+
} catch {
|
|
148
|
+
return [pscustomobject]@{
|
|
149
|
+
skipped = $false
|
|
150
|
+
success = $false
|
|
151
|
+
exitCode = -1
|
|
152
|
+
stderr = "Failed to download the Devin installer: $($_.Exception.Message)"
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
$installerLines = [regex]::Split([string]$installerSource, '\r?\n')
|
|
157
|
+
$setupMatches = @($installerLines | Where-Object { $_ -match '^\s*&\s+\$EntryExe\s+setup\s*$' })
|
|
158
|
+
if ($setupMatches.Count -ne 1) {
|
|
159
|
+
return [pscustomobject]@{
|
|
160
|
+
skipped = $false
|
|
161
|
+
success = $false
|
|
162
|
+
exitCode = -1
|
|
163
|
+
stderr = ("Refusing to run the Devin installer: expected exactly one interactive setup " +
|
|
164
|
+
"invocation, found $($setupMatches.Count). Install Devin with the upstream installer and report this.")
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
$patchedLines = $installerLines | ForEach-Object {
|
|
169
|
+
if ($_ -match '^\s*&\s+\$EntryExe\s+setup\s*$') {
|
|
170
|
+
'# skipped interactive devin setup (packaged setup runs non-interactively)'
|
|
171
|
+
} else {
|
|
172
|
+
$_
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
$bootstrap = ($patchedLines -join [Environment]::NewLine)
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
[System.IO.File]::WriteAllText(
|
|
179
|
+
$tempScript,
|
|
180
|
+
$bootstrap,
|
|
181
|
+
[System.Text.UTF8Encoding]::new($false)
|
|
182
|
+
)
|
|
183
|
+
$powerShellExe = if (Get-Command pwsh.exe -ErrorAction SilentlyContinue) {
|
|
184
|
+
'pwsh.exe'
|
|
185
|
+
} else {
|
|
186
|
+
'powershell.exe'
|
|
187
|
+
}
|
|
188
|
+
$process = Start-Process -FilePath $powerShellExe `
|
|
189
|
+
-ArgumentList @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $tempScript) `
|
|
190
|
+
-Wait -PassThru -NoNewWindow `
|
|
191
|
+
-RedirectStandardOutput $stdoutPath `
|
|
192
|
+
-RedirectStandardError $stderrPath
|
|
193
|
+
$stderrRaw = if (Test-Path -LiteralPath $stderrPath -PathType Leaf) {
|
|
194
|
+
Get-Content -LiteralPath $stderrPath -Raw -ErrorAction SilentlyContinue
|
|
195
|
+
} else { $null }
|
|
196
|
+
|
|
197
|
+
return [pscustomobject]@{
|
|
198
|
+
skipped = $false
|
|
199
|
+
success = ($process.ExitCode -eq 0)
|
|
200
|
+
exitCode = $process.ExitCode
|
|
201
|
+
stderr = if ($null -eq $stderrRaw) { '' } else { [string]$stderrRaw }
|
|
202
|
+
}
|
|
203
|
+
} catch {
|
|
204
|
+
return [pscustomobject]@{
|
|
205
|
+
skipped = $false
|
|
206
|
+
success = $false
|
|
207
|
+
exitCode = -1
|
|
208
|
+
stderr = "Failed to invoke Devin installer: $($_.Exception.Message)"
|
|
209
|
+
}
|
|
210
|
+
} finally {
|
|
211
|
+
foreach ($path in @($tempScript, $stdoutPath, $stderrPath)) {
|
|
212
|
+
if (Test-Path -LiteralPath $path -PathType Leaf) {
|
|
213
|
+
Remove-Item -LiteralPath $path -Force -ErrorAction SilentlyContinue
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (-not $CheckOnly -and -not $Apply -and -not $Upgrade -and -not $Force -and -not $Uninstall) {
|
|
220
|
+
$CheckOnly = $true
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
$mutationCount = @($Apply, $Upgrade, $Force | Where-Object { $_ }).Count
|
|
224
|
+
if ($Uninstall -and ($CheckOnly -or $mutationCount -gt 0)) {
|
|
225
|
+
throw 'Install-Devin.ps1 -Uninstall is mutually exclusive with other modes.'
|
|
226
|
+
}
|
|
227
|
+
if ($CheckOnly -and $mutationCount -gt 0) {
|
|
228
|
+
throw 'Install-Devin.ps1 accepts either -CheckOnly or one mutation mode.'
|
|
229
|
+
}
|
|
230
|
+
if ($mutationCount -gt 1) {
|
|
231
|
+
throw 'Install-Devin.ps1 accepts at most one of -Apply / -Upgrade / -Force.'
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
$executionMode = if ($Uninstall) {
|
|
235
|
+
'uninstall'
|
|
236
|
+
} elseif ($CheckOnly) {
|
|
237
|
+
'check'
|
|
238
|
+
} elseif ($Force) {
|
|
239
|
+
'force'
|
|
240
|
+
} elseif ($Upgrade) {
|
|
241
|
+
'upgrade'
|
|
242
|
+
} else {
|
|
243
|
+
'apply'
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if ($Uninstall) {
|
|
247
|
+
Invoke-PackagedProviderUninstall `
|
|
248
|
+
-HelperId 'windows-devin-native-installer' `
|
|
249
|
+
-UserBinaryPath (Resolve-DevinExecutablePath) `
|
|
250
|
+
-ExtraUserOwnedPaths @((Join-Path $env:LOCALAPPDATA 'devin\cli')) `
|
|
251
|
+
-RedetectCommand { Detect-DevinInstall } `
|
|
252
|
+
-EmitJson:$Json `
|
|
253
|
+
-DryRun:$DryRun
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).
|
|
257
|
+
IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
|
258
|
+
if ($isAdmin -and -not $AllowAdmin) {
|
|
259
|
+
Write-StructuredResult -Result ([pscustomobject]@{
|
|
260
|
+
helper = 'windows-devin-native-installer'
|
|
261
|
+
mode = $executionMode
|
|
262
|
+
status = 'failed'
|
|
263
|
+
installed = $false
|
|
264
|
+
detectedVersion = $null
|
|
265
|
+
commandPath = Resolve-DevinExecutablePath
|
|
266
|
+
restartRequired = $false
|
|
267
|
+
plannedActions = @()
|
|
268
|
+
warnings = @('Refusing to run under an elevated shell without -AllowAdmin because Devin CLI is intended for user-scoped installation.')
|
|
269
|
+
appliedChanges = @()
|
|
270
|
+
manualSteps = @()
|
|
271
|
+
interruptions = @()
|
|
272
|
+
}) -ExitCode 1
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
$detected = Detect-DevinInstall
|
|
276
|
+
$plannedActions = [System.Collections.Generic.List[string]]::new()
|
|
277
|
+
$appliedChanges = [System.Collections.Generic.List[string]]::new()
|
|
278
|
+
$warnings = [System.Collections.Generic.List[string]]::new()
|
|
279
|
+
$manualSteps = [System.Collections.Generic.List[string]]::new()
|
|
280
|
+
|
|
281
|
+
if ($Force) {
|
|
282
|
+
$plannedActions.Add('reinstall_devin_native')
|
|
283
|
+
} elseif ($Upgrade -and $detected.installed) {
|
|
284
|
+
$plannedActions.Add('upgrade_devin_native')
|
|
285
|
+
} elseif (-not $detected.installed) {
|
|
286
|
+
$plannedActions.Add('install_devin_native')
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if ($CheckOnly) {
|
|
290
|
+
Write-StructuredResult -Result ([pscustomobject]@{
|
|
291
|
+
helper = 'windows-devin-native-installer'
|
|
292
|
+
mode = 'check'
|
|
293
|
+
status = if ($detected.installed) { 'ready' } else { 'not_installed' }
|
|
294
|
+
installed = [bool]$detected.installed
|
|
295
|
+
detectedVersion = if ($detected.detectedVersion) { $detected.detectedVersion } else { $null }
|
|
296
|
+
commandPath = $detected.commandPath
|
|
297
|
+
restartRequired = $false
|
|
298
|
+
plannedActions = $plannedActions.ToArray()
|
|
299
|
+
warnings = @()
|
|
300
|
+
appliedChanges = @()
|
|
301
|
+
manualSteps = @()
|
|
302
|
+
interruptions = @()
|
|
303
|
+
}) -ExitCode 0
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
$shouldInstall = $Force -or $Upgrade -or -not $detected.installed
|
|
307
|
+
$installFailed = $false
|
|
308
|
+
$installSkipped = $false
|
|
309
|
+
if ($shouldInstall) {
|
|
310
|
+
if ($DryRun) {
|
|
311
|
+
$warnings.Add('Dry-run requested; Devin installer invocation was skipped.')
|
|
312
|
+
$installSkipped = $true
|
|
313
|
+
} else {
|
|
314
|
+
$installResult = Invoke-DevinInstaller
|
|
315
|
+
$installSkipped = [bool]$installResult.skipped
|
|
316
|
+
$installFailed = (-not $installSkipped) -and (-not $installResult.success)
|
|
317
|
+
if ($installSkipped) {
|
|
318
|
+
$warnings.Add('Installer invocation was skipped by request.')
|
|
319
|
+
} elseif ($installFailed) {
|
|
320
|
+
$stderrSnippet = if ([string]::IsNullOrWhiteSpace($installResult.stderr)) {
|
|
321
|
+
'no stderr captured'
|
|
322
|
+
} else {
|
|
323
|
+
($installResult.stderr.Trim() -split "`r?`n" |
|
|
324
|
+
Where-Object { -not [string]::IsNullOrWhiteSpace($_) } |
|
|
325
|
+
Select-Object -Last 8) -join ' | '
|
|
326
|
+
}
|
|
327
|
+
$warnings.Add("Devin installer exited $($installResult.exitCode): $stderrSnippet")
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
Start-Sleep -Seconds 2
|
|
331
|
+
Add-DevinToUserPath
|
|
332
|
+
$detected = Detect-DevinInstall
|
|
333
|
+
if (-not $detected.installed -and -not $installSkipped -and -not $installFailed) {
|
|
334
|
+
$warnings.Add('Devin installation completed but devin.exe was not detected at the expected path.')
|
|
335
|
+
$installFailed = $true
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (-not $installFailed -and -not ($DryRun -and $shouldInstall)) {
|
|
340
|
+
if ($Force) {
|
|
341
|
+
$appliedChanges.Add('reinstall_devin_native')
|
|
342
|
+
} elseif ($Upgrade) {
|
|
343
|
+
$appliedChanges.Add('upgrade_devin_native')
|
|
344
|
+
} else {
|
|
345
|
+
$appliedChanges.Add('install_devin_native')
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
$manualSteps.Add('Run `devin login` or set XAI_API_KEY before first use.')
|
|
351
|
+
$interruptions = [System.Collections.Generic.List[object]]::new()
|
|
352
|
+
if ($shouldInstall -and -not $installFailed -and -not $DryRun) {
|
|
353
|
+
$interruptions.Add([pscustomobject]@{
|
|
354
|
+
kind = 'relaunch_required'
|
|
355
|
+
summary = 'Relaunch Cats Desktop Host after the Devin install step, then rerun the packaged setup check.'
|
|
356
|
+
resumable = $true
|
|
357
|
+
requiresRestart = $false
|
|
358
|
+
requiresElevation = $false
|
|
359
|
+
})
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
$status = if ($installFailed) {
|
|
363
|
+
'failed'
|
|
364
|
+
} elseif ($DryRun -and $shouldInstall) {
|
|
365
|
+
'preview'
|
|
366
|
+
} elseif ($interruptions.Count -gt 0) {
|
|
367
|
+
[string]$interruptions[0].kind
|
|
368
|
+
} else {
|
|
369
|
+
'ready'
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
Write-StructuredResult -Result ([pscustomobject]@{
|
|
373
|
+
helper = 'windows-devin-native-installer'
|
|
374
|
+
mode = $executionMode
|
|
375
|
+
status = $status
|
|
376
|
+
installed = [bool]$detected.installed
|
|
377
|
+
detectedVersion = if ($detected.detectedVersion) { $detected.detectedVersion } else { $null }
|
|
378
|
+
commandPath = $detected.commandPath
|
|
379
|
+
restartRequired = $false
|
|
380
|
+
plannedActions = $plannedActions.ToArray()
|
|
381
|
+
warnings = $warnings.ToArray()
|
|
382
|
+
appliedChanges = $appliedChanges.ToArray()
|
|
383
|
+
manualSteps = $manualSteps.ToArray()
|
|
384
|
+
interruptions = $interruptions.ToArray()
|
|
385
|
+
}) -ExitCode $(if ($installFailed) { 1 } else { 0 })
|