This commit is contained in:
1 parent
9b5e862d8a
commit
c6c8bf7105
5 files changed
+63
-76
No files matched your search
@@ -1,59 +1,35 @@
|
||||
function Read-InstallPlatform {
|
||||
param([string]$Platform)
|
||||
if ($Platform) { return $Platform }
|
||||
Write-Host 'Select target platform:'
|
||||
Write-Host '1) Windows'
|
||||
Write-Host '2) Linux'
|
||||
do { $selection = Read-Host 'Selection [1-2]' } while ($selection -notin @('1','2'))
|
||||
return @{'1'='Windows'; '2'='Linux'}[$selection]
|
||||
return Read-InteractiveSingle -Title 'Select shell' -Names @('PowerShell','Bash') -Values @('Windows','Linux')
|
||||
}
|
||||
|
||||
function Read-InstallClient {
|
||||
param([string]$Client)
|
||||
if ($Client) { return $Client }
|
||||
Write-Host 'Select installation target:'
|
||||
Write-Host '1) Codex'
|
||||
Write-Host '2) Claude'
|
||||
Write-Host '3) Both'
|
||||
do { $selection = Read-Host 'Selection [1-3]' } while ($selection -notin @('1','2','3'))
|
||||
return @{'1'='Codex'; '2'='Claude'; '3'='Both'}[$selection]
|
||||
return Read-InteractiveSingle -Title 'Select client' -Names @('Codex','Claude','Both') -Values @('Codex','Claude','Both')
|
||||
}
|
||||
function Clear-InteractiveScreen { if (-not [Console]::IsInputRedirected -and $env:CI -ne 'true' -and $env:AI_CONFIG_NO_INTERACTIVE -ne '1') { Clear-Host } }
|
||||
function Read-InteractiveSingle {
|
||||
param([string]$Title,[string[]]$Names,[string[]]$Values)
|
||||
if ([Console]::IsInputRedirected -or $env:CI -eq 'true' -or $env:AI_CONFIG_NO_INTERACTIVE -eq '1') {
|
||||
Write-Host $Title; for($i=0;$i -lt $Names.Count;$i++){ Write-Host ('{0}) {1}' -f ($i+1),$Names[$i]) }
|
||||
do { $answer=Read-Host 'Selection' } while($answer -notmatch ('^[1-{0}]$' -f $Names.Count)); return $Values[[int]$answer-1]
|
||||
}
|
||||
$index=0
|
||||
while($true) {
|
||||
Clear-InteractiveScreen; Write-Host $Title
|
||||
for($i=0;$i -lt $Names.Count;$i++){ $prefix=if($i -eq $index){'>'}else{' '}; if($i -eq $index -and $env:NO_COLOR -ne '1'){Write-Host ('{0} {1}' -f $prefix,$Names[$i]) -ForegroundColor Cyan}else{Write-Host ('{0} {1}' -f $prefix,$Names[$i])} }
|
||||
Write-Host 'Up/Down Navigate Enter Confirm'; $key=[Console]::ReadKey($true)
|
||||
if($key.Key -eq 'Up'){ $index=($index+$Names.Count-1)%$Names.Count } elseif($key.Key -eq 'Down'){ $index=($index+1)%$Names.Count } elseif($key.Key -eq 'Enter'){ Clear-InteractiveScreen; return $Values[$index] }
|
||||
}
|
||||
}
|
||||
|
||||
function Get-InstallDestinations {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$HomePath,
|
||||
[ValidateSet('Codex','Claude','Both')][Parameter(Mandatory=$true)][string]$Client
|
||||
)
|
||||
$destinations = @()
|
||||
if ($Client -in @('Codex','Both')) { $destinations += Join-Path $HomePath '.codex' }
|
||||
if ($Client -in @('Claude','Both')) { $destinations += Join-Path $HomePath '.claude' }
|
||||
return $destinations
|
||||
param([Parameter(Mandatory=$true)][string]$HomePath,[ValidateSet('Codex','Claude','Both')][Parameter(Mandatory=$true)][string]$Client)
|
||||
$destinations=@(); if($Client -in @('Codex','Both')){$destinations+=Join-Path $HomePath '.codex'}; if($Client -in @('Claude','Both')){$destinations+=Join-Path $HomePath '.claude'}; return $destinations
|
||||
}
|
||||
|
||||
function Get-InstallTargets {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$Generated,
|
||||
[Parameter(Mandatory=$true)][string]$HomePath,
|
||||
[Parameter(Mandatory=$true)][string]$Platform,
|
||||
[ValidateSet('Codex','Claude','Both')][Parameter(Mandatory=$true)][string]$Client
|
||||
)
|
||||
$targets = @()
|
||||
if ($Client -in @('Codex','Both')) {
|
||||
$targets += @{ Source=(Join-Path $Generated "codex-$Platform"); Destination=(Join-Path $HomePath '.codex') }
|
||||
$targets += @{ Source=(Join-Path $Generated "codex-$Platform/skills"); Destination=(Join-Path $HomePath '.agents/skills') }
|
||||
}
|
||||
if ($Client -in @('Claude','Both')) {
|
||||
$targets += @{ Source=(Join-Path $Generated "claude-$Platform"); Destination=(Join-Path $HomePath '.claude') }
|
||||
}
|
||||
return $targets
|
||||
}
|
||||
|
||||
function Test-AnyManifestPresent {
|
||||
param([Parameter(Mandatory=$true)][string[]]$Destinations)
|
||||
return [bool](@($Destinations | Where-Object { Test-Path (Get-ManagedManifestPath $_) }).Count)
|
||||
}
|
||||
|
||||
function Test-AllManifestsPresent {
|
||||
param([Parameter(Mandatory=$true)][string[]]$Destinations)
|
||||
return [bool](@($Destinations | Where-Object { -not (Test-Path (Get-ManagedManifestPath $_)) }).Count -eq 0)
|
||||
param([Parameter(Mandatory=$true)][string]$Generated,[Parameter(Mandatory=$true)][string]$HomePath,[Parameter(Mandatory=$true)][string]$Platform,[ValidateSet('Codex','Claude','Both')][Parameter(Mandatory=$true)][string]$Client)
|
||||
$targets=@(); if($Client -in @('Codex','Both')){$targets+=@{Source=(Join-Path $Generated "codex-$Platform");Destination=(Join-Path $HomePath '.codex')};$targets+=@{Source=(Join-Path $Generated "codex-$Platform/skills");Destination=(Join-Path $HomePath '.agents/skills')}}; if($Client -in @('Claude','Both')){$targets+=@{Source=(Join-Path $Generated "claude-$Platform");Destination=(Join-Path $HomePath '.claude')};}; return $targets
|
||||
}
|
||||
function Test-AnyManifestPresent { param([Parameter(Mandatory=$true)][string[]]$Destinations); return [bool](@($Destinations|Where-Object{Test-Path(Get-ManagedManifestPath $_)}).Count) }
|
||||
function Test-AllManifestsPresent { param([Parameter(Mandatory=$true)][string[]]$Destinations); return [bool](@($Destinations|Where-Object{-not(Test-Path(Get-ManagedManifestPath $_))}).Count -eq 0) }
|
||||
@@ -9,12 +9,7 @@ read_install_platform() {
|
||||
*) printf 'Unknown --platform value: %s (expected windows or linux)\n' "$platform" >&2; return 1 ;;
|
||||
esac
|
||||
fi
|
||||
printf 'Select target platform:\n1) Windows\n2) Linux\n' >&2
|
||||
local selection
|
||||
while :; do
|
||||
read -r -p 'Selection [1-2] ' selection
|
||||
case "$selection" in 1) printf 'windows\n'; return 0 ;; 2) printf 'linux\n'; return 0 ;; esac
|
||||
done
|
||||
read_single_selection 'Select shell' 'PowerShell' 'windows' 'Bash' 'linux'
|
||||
}
|
||||
|
||||
read_install_client() {
|
||||
@@ -27,12 +22,15 @@ read_install_client() {
|
||||
*) printf 'Unknown --client value: %s (expected codex, claude, or both)\n' "$client" >&2; return 1 ;;
|
||||
esac
|
||||
fi
|
||||
printf 'Select installation target:\n1) Codex\n2) Claude\n3) Both\n' >&2
|
||||
local selection
|
||||
while :; do
|
||||
read -r -p 'Selection [1-3] ' selection
|
||||
case "$selection" in 1) printf 'codex\n'; return 0 ;; 2) printf 'claude\n'; return 0 ;; 3) printf 'both\n'; return 0 ;; esac
|
||||
done
|
||||
read_single_selection 'Select client' 'Codex' 'codex' 'Claude' 'claude' 'Both' 'both'
|
||||
}
|
||||
|
||||
clear_interactive() { [ -t 0 ] && [ "${CI:-}" != true ] && [ "${AI_CONFIG_NO_INTERACTIVE:-}" != 1 ] && printf '\033[2J\033[H'; }
|
||||
read_single_selection() {
|
||||
local title=$1; shift; local labels=() values=() label value index=0 key
|
||||
while [ $# -gt 0 ]; do labels+=("$1"); values+=("$2"); shift 2; done
|
||||
if [ ! -t 0 ] || [ "${CI:-}" = true ] || [ "${AI_CONFIG_NO_INTERACTIVE:-}" = 1 ]; then printf '%s\n' "$title" >&2; for ((index=0;index<${#labels[@]};index++)); do printf '%d) %s\n' "$((index+1))" "${labels[$index]}" >&2; done; while read -r -p 'Selection ' value; do [[ "$value" =~ ^[1-9][0-9]*$ ]] && [ "$value" -le "${#labels[@]}" ] && { printf '%s\n' "${values[$((value-1))]}"; return; }; done; return 1; fi
|
||||
local selected=0; while :; do clear_interactive; printf '%s\n' "$title"; for ((index=0;index<${#labels[@]};index++)); do [ "$index" -eq "$selected" ] && printf '> %s\n' "${labels[$index]}" || printf ' %s\n' "${labels[$index]}"; done; printf '↑/↓ Navigate Enter Confirm\n'; IFS= read -rsn1 key || return 1; case "$key" in $'\x1b') read -rsn2 key; case "$key" in '[A') selected=$(( (selected+${#labels[@]}-1)%${#labels[@]} ));; '[B') selected=$(( (selected+1)%${#labels[@]} ));; esac;; '') clear_interactive; printf '%s\n' "${values[$selected]}"; return;; esac; done
|
||||
}
|
||||
|
||||
# get_install_destinations <home> <client> -- prints one destination per line
|
||||
|
||||
+14
-15
@@ -19,7 +19,7 @@ function Invoke-PluginCommand {
|
||||
$output = @(& $resolvedCommand @Arguments 2>&1)
|
||||
$exitCode = $LASTEXITCODE
|
||||
} finally { $ErrorActionPreference = $previousPreference }
|
||||
$output | Where-Object { -not $Summary -or $exitCode -ne 0 -or $_ -is [System.Management.Automation.ErrorRecord] -or "$_" -match '(?i)warn|error|fail|deprecat' }
|
||||
if (-not $Summary -or $env:AI_CONFIG_VERBOSE -eq '1') { $output | Write-Output } elseif ($exitCode -eq 0) { $output | Where-Object { "$_" -match '(?i)warn|error|fail|deprecat' } }
|
||||
if ($exitCode -ne 0) { throw "Plugin command failed: $display" }
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ function Ensure-CodexMarketplace {
|
||||
} finally {
|
||||
$ErrorActionPreference = $previousErrorActionPreference
|
||||
}
|
||||
$output | Where-Object { -not $Summary -or $exitCode -ne 0 -or $_ -is [System.Management.Automation.ErrorRecord] -or "$_" -match '(?i)warn|error|fail|deprecat' }
|
||||
if (-not $Summary -or $env:AI_CONFIG_VERBOSE -eq '1') { $output | Write-Output } elseif ($exitCode -eq 0) { $output | Where-Object { "$_" -match '(?i)warn|error|fail|deprecat' } }
|
||||
if ($exitCode -eq 0) { return }
|
||||
|
||||
$text = $output -join [Environment]::NewLine
|
||||
@@ -87,19 +87,14 @@ function Read-PluginToggleSelection {
|
||||
[Parameter(Mandatory=$true)][bool[]]$Checked
|
||||
)
|
||||
$state = @($Checked)
|
||||
while ($true) {
|
||||
Write-Host 'Select plugins (enter a number to toggle, "done" to confirm):'
|
||||
for ($i = 0; $i -lt $Names.Count; $i++) {
|
||||
$mark = if ($state[$i]) { 'x' } else { ' ' }
|
||||
Write-Host (" {0}) [{1}] {2}" -f ($i + 1), $mark, $Names[$i])
|
||||
}
|
||||
$answer = Read-Host 'Toggle number or "done"'
|
||||
if ([string]::IsNullOrWhiteSpace($answer) -or $answer -eq 'done') { return $state }
|
||||
$index = 0
|
||||
if ([int]::TryParse($answer, [ref]$index) -and $index -ge 1 -and $index -le $Names.Count) {
|
||||
$state[$index - 1] = -not $state[$index - 1]
|
||||
}
|
||||
}
|
||||
if ([Console]::IsInputRedirected -or $env:CI -eq 'true' -or $env:AI_CONFIG_NO_INTERACTIVE -eq '1') { while($true){ Write-Host 'Select plugins (enter a number to toggle, "done" to confirm):'; for($i=0;$i -lt $Names.Count;$i++){Write-Host (" {0}) [{1}] {2}" -f ($i+1),$(if($state[$i]){'x'}else{' '}),$Names[$i])}; $answer=Read-Host 'Toggle number or "done"'; if([string]::IsNullOrWhiteSpace($answer)-or $answer -eq 'done'){return $state}; $index=0;if([int]::TryParse($answer,[ref]$index)-and $index -ge 1 -and $index -le $Names.Count){$state[$index-1]= -not $state[$index-1]} } }
|
||||
$index=0; while($true){ Clear-Host; Write-Host 'Select plugins'; for($i=0;$i -lt $Names.Count;$i++){ $focus=if($i -eq $index){'>'}else{' '}; $mark=if($state[$i]){'x'}else{' '}; Write-Host "$focus [$mark] $($Names[$i])" }; Write-Host '↑/↓ Navigate Space Toggle Enter Confirm'; $key=[Console]::ReadKey($true); if($key.Key -eq 'Up'){$index=($index+$Names.Count-1)%$Names.Count}elseif($key.Key -eq 'Down'){$index=($index+1)%$Names.Count}elseif($key.Key -eq 'Spacebar'){$state[$index]= -not $state[$index]}elseif($key.Key -eq 'Enter'){Clear-Host;return $state} }
|
||||
}
|
||||
|
||||
function Update-CodexMarketplace {
|
||||
param([Parameter(Mandatory=$true)][string]$MarketplaceName,[Parameter(Mandatory=$true)][string]$Source,[switch]$DryRun,[switch]$Summary)
|
||||
try { Invoke-PluginCommand -Command 'codex' -Arguments @('plugin','marketplace','upgrade',$MarketplaceName) -DryRun:$DryRun -Summary:$Summary }
|
||||
catch { Ensure-CodexMarketplace -Source $Source -MarketplaceName $MarketplaceName -DryRun:$DryRun -Summary:$Summary }
|
||||
}
|
||||
|
||||
function Select-ConfiguredPlugins {
|
||||
@@ -231,6 +226,9 @@ function Install-ConfiguredPlugins {
|
||||
}
|
||||
Invoke-PluginCommand -Command 'claude' -Arguments @('plugin','install',$plugin,'--scope','user') -DryRun:$DryRun -Summary:$Summary
|
||||
} else {
|
||||
if ($Update -and -not [string]::IsNullOrWhiteSpace($marketplace) -and $marketplace -ne 'openai-curated-remote') {
|
||||
Update-CodexMarketplace -MarketplaceName (($plugin -split '@')[-1]) -Source $marketplace -DryRun:$DryRun -Summary:$Summary
|
||||
}
|
||||
if (-not [string]::IsNullOrWhiteSpace($marketplace) -and $marketplace -ne 'openai-curated-remote') {
|
||||
$marketplaceName = ($plugin -split '@')[-1]
|
||||
Ensure-CodexMarketplace -Source $marketplace -MarketplaceName $marketplaceName -DryRun:$DryRun -Summary:$Summary
|
||||
@@ -243,3 +241,4 @@ function Install-ConfiguredPlugins {
|
||||
if ($Summary) { Write-Output ("PLUGINS {0}: {1} ensured, {2} already installed, {3} updated" -f $selectedClient, $tally.Ensured, $tally.AlreadyInstalled, $tally.Updated) }
|
||||
}
|
||||
}
|
||||
|
||||
+14
-2
@@ -22,7 +22,8 @@ run_plugin_command() {
|
||||
printf '%s\n' "$output" | grep -Ei 'warn|error|fail|deprecat' || true
|
||||
else
|
||||
status=$?
|
||||
printf '%s\n' "$output" >&2
|
||||
[ "${AI_CONFIG_VERBOSE:-}" = 1 ] && printf '%s\n' "$output" >&2
|
||||
printf 'Plugin command failed: %s\n' "$*" >&2
|
||||
return "$status"
|
||||
fi
|
||||
else
|
||||
@@ -30,6 +31,13 @@ run_plugin_command() {
|
||||
fi
|
||||
}
|
||||
|
||||
update_codex_marketplace() {
|
||||
local dry_run=$1 marketplace_name=$2 source=$3
|
||||
if ! run_plugin_command "$dry_run" codex plugin marketplace upgrade "$marketplace_name"; then
|
||||
ensure_codex_marketplace "$dry_run" "$source" "$marketplace_name"
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_codex_marketplace() {
|
||||
local dry_run=$1 source=$2 marketplace_name=$3 output
|
||||
if [ "$dry_run" = true ]; then
|
||||
@@ -81,7 +89,10 @@ plugin_toggleable() {
|
||||
read_plugin_toggle_selection() {
|
||||
local -n names_ref=$1
|
||||
local -n checked_ref=$2
|
||||
local answer i mark
|
||||
local answer i mark index=0 key
|
||||
if [ -t 0 ] && [ "${CI:-}" != true ] && [ "${AI_CONFIG_NO_INTERACTIVE:-}" != 1 ]; then
|
||||
while :; do clear_interactive; printf 'Select plugins\n'; for ((i=0;i<${#names_ref[@]};i++)); do mark=' '; [ "${checked_ref[$i]}" = true ] && mark=x; [ "$i" -eq "$index" ] && printf '> [%s] %s\n' "$mark" "${names_ref[$i]}" || printf ' [%s] %s\n' "$mark" "${names_ref[$i]}"; done; printf '↑/↓ Navigate Space Toggle Enter Confirm\n'; IFS= read -rsn1 key || return 1; case "$key" in $'\x1b') read -rsn2 key; case "$key" in '[A') index=$(( (index+${#names_ref[@]}-1)%${#names_ref[@]} ));; '[B') index=$(( (index+1)%${#names_ref[@]} ));; esac;; ' ') [ "${checked_ref[$index]}" = true ] && checked_ref[$index]=false || checked_ref[$index]=true;; '') clear_interactive; return 0;; esac; done
|
||||
fi
|
||||
while :; do
|
||||
printf 'Select plugins (enter a number to toggle, "done" to confirm):\n'
|
||||
for ((i = 0; i < ${#names_ref[@]}; i++)); do
|
||||
@@ -227,6 +238,7 @@ install_configured_plugins() {
|
||||
run_plugin_command "$dry_run" claude plugin enable "$plugin"
|
||||
updated_count=$((updated_count + 1))
|
||||
elif [ "$update" = true ] && [ "$client" = codex ]; then
|
||||
[ -z "$marketplace" ] || [ "$marketplace" = openai-curated-remote ] || update_codex_marketplace "$dry_run" "${plugin##*@}" "$marketplace"
|
||||
run_plugin_command "$dry_run" codex plugin add "$plugin"
|
||||
updated_count=$((updated_count + 1))
|
||||
else
|
||||
|
||||
@@ -30,8 +30,10 @@ $detailed = @(Invoke-PluginCommand -Command Test-PluginOutput -Arguments @('succ
|
||||
if ($detailed.Count -ne 2 -or $detailed[0] -ne 'download progress') { throw 'Detailed output must retain progress.' }
|
||||
$diagnostics = [System.Collections.Generic.List[string]]::new()
|
||||
$failed = $false
|
||||
$env:AI_CONFIG_VERBOSE = '1'
|
||||
try { Invoke-PluginCommand -Command Test-PluginOutput -Arguments @('fail') -Summary | ForEach-Object { $diagnostics.Add("$_") } }
|
||||
catch { $failed = $true }
|
||||
$env:AI_CONFIG_VERBOSE = $null
|
||||
if (-not $failed -or $diagnostics -notcontains 'download progress' -or $diagnostics -notcontains 'WARN test warning') { throw 'Plugin failure must retain full diagnostics and fail.' }
|
||||
$global:LASTEXITCODE = 0
|
||||
function Get-InstalledPlugins { [pscustomobject]@{ pluginId = 'test@market' } }
|
||||
|
||||
Reference in new issue
Block a user