feat(update): persist interactive install choices
This commit is contained in:
1 parent
80e1ab440e
commit
9a2a606410
14 files changed
+557
-82
No files matched your search
@@ -0,0 +1,72 @@
|
||||
function Read-InstallBoolean {
|
||||
param([string]$Prompt, [bool]$Default)
|
||||
$hint = if ($Default) { 'Y/n' } else { 'y/N' }
|
||||
while ($true) {
|
||||
Write-Host "$Prompt [$hint] " -NoNewline
|
||||
$answer = [Console]::ReadLine()
|
||||
if ($null -eq $answer) { throw 'Input ended before install options were confirmed.' }
|
||||
switch ($answer.Trim().ToLowerInvariant()) {
|
||||
'' { return $Default }
|
||||
{ $_ -in @('y', 'yes') } { return $true }
|
||||
{ $_ -in @('n', 'no') } { return $false }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Read-InstallOptions {
|
||||
param([string]$HomePath, [string]$RepositoryRoot, [string]$Client, [switch]$DryRun)
|
||||
$defaults = @{ update_agents = $false; flashbang = $true }
|
||||
if (Test-Path -LiteralPath (Join-Path $HomePath '.my-ai-configuration/selection.json')) {
|
||||
try { $defaults = Read-UpdateSelection -HomePath $HomePath -RepositoryRoot $RepositoryRoot -AllowLegacy }
|
||||
catch { Write-Warning 'Saved options could not be read; confirm new options below.' }
|
||||
}
|
||||
if ($DryRun) { return $defaults }
|
||||
return @{
|
||||
update_agents = Read-InstallBoolean -Prompt "Update selected agent CLIs ($Client)?" -Default $defaults.update_agents
|
||||
flashbang = Read-InstallBoolean -Prompt 'Enable the Flashbang notification hook?' -Default $defaults.flashbang
|
||||
}
|
||||
}
|
||||
|
||||
function Test-CodexProcessActive {
|
||||
if ([Environment]::OSVersion.Platform -ne [PlatformID]::Win32NT) { return $false }
|
||||
return [bool](Get-Process -Name 'codex' -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
function Test-GlobalNpmCodex {
|
||||
$npm = Get-Command npm -ErrorAction SilentlyContinue
|
||||
if (-not $npm) { return $false }
|
||||
$previousPreference = $ErrorActionPreference
|
||||
try {
|
||||
$ErrorActionPreference = 'Continue'
|
||||
& $npm list -g '@openai/codex' --depth=0 --json 1>$null 2>$null
|
||||
return $LASTEXITCODE -eq 0
|
||||
} finally {
|
||||
$ErrorActionPreference = $previousPreference
|
||||
}
|
||||
}
|
||||
|
||||
function Update-SelectedAgentClis {
|
||||
param([string]$Client, [switch]$DryRun, [switch]$Summary)
|
||||
$clients = if ($Client -eq 'Both') { @('codex', 'claude') } else { @($Client.ToLowerInvariant()) }
|
||||
$previousNonInteractive = $script:PluginNonInteractive
|
||||
$previousAutoUpdate = $env:CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE
|
||||
try {
|
||||
$script:PluginNonInteractive = $true
|
||||
$env:CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE = '1'
|
||||
foreach ($selectedClient in $clients) {
|
||||
if ($selectedClient -eq 'codex' -and -not $DryRun -and (Test-CodexProcessActive)) {
|
||||
Write-Warning 'Codex CLI update skipped because codex.exe is running. Close all Codex sessions and run the update again to update the CLI.'
|
||||
continue
|
||||
}
|
||||
if ($selectedClient -eq 'codex' -and (Test-GlobalNpmCodex)) {
|
||||
Invoke-PluginCommand -Command 'npm' -Arguments @('install','-g','@openai/codex@latest') -DryRun:$DryRun -Summary:$Summary
|
||||
} else {
|
||||
Invoke-PluginCommand -Command $selectedClient -Arguments @('update') -DryRun:$DryRun -Summary:$Summary
|
||||
}
|
||||
if ($Summary) { Write-Output "CLI $selectedClient update: $(if ($DryRun) { 'dry-run' } else { 'PASS' })" }
|
||||
}
|
||||
} finally {
|
||||
$script:PluginNonInteractive = $previousNonInteractive
|
||||
$env:CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE = $previousAutoUpdate
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
import re
|
||||
import sys
|
||||
import tomllib
|
||||
|
||||
|
||||
def is_flashbang(hook):
|
||||
return any(re.search(r'(?:[/\\\s"\x27]|^)flashbang\.(?:ps1|sh)(?:[\s"\x27]|$)', str(hook.get(key, '')), re.I)
|
||||
for key in ('command', 'command_windows'))
|
||||
|
||||
|
||||
def filter_flashbang(path):
|
||||
content = path.read_text(encoding='utf-8-sig')
|
||||
if path.name == 'settings.json':
|
||||
settings = json.loads(content)
|
||||
groups = settings.get('hooks', {}).get('Stop', [])
|
||||
remaining = []
|
||||
for group in groups:
|
||||
hooks = [hook for hook in group.get('hooks', []) if not is_flashbang(hook)]
|
||||
if hooks:
|
||||
remaining.append(dict(group, hooks=hooks))
|
||||
if remaining:
|
||||
settings['hooks']['Stop'] = remaining
|
||||
elif 'Stop' in settings.get('hooks', {}):
|
||||
del settings['hooks']['Stop']
|
||||
return json.dumps(settings, indent=2, ensure_ascii=False) + '\n'
|
||||
if path.name != 'config.toml':
|
||||
raise ValueError('Flashbang filtering only supports client configuration files.')
|
||||
tomllib.loads(content)
|
||||
sections = re.split(r'(?m)(?=^\s*\[\[?[^\r\n]+\]\]?\s*$)', content)
|
||||
filtered = []
|
||||
for section in sections:
|
||||
if re.match(r'\s*\[\[hooks\.Stop\.hooks\]\]', section):
|
||||
hook = tomllib.loads(section)['hooks']['Stop']['hooks'][0]
|
||||
if is_flashbang(hook):
|
||||
continue
|
||||
filtered.append(section)
|
||||
result = ''.join(filtered)
|
||||
result = re.sub(r'(?m)^\[\[hooks\.Stop\]\][ \t]*\r?\n\s*(?=\[|\Z)(?!\[\[hooks\.Stop\.hooks\]\])', '', result)
|
||||
tomllib.loads(result)
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('action', choices=('filter',))
|
||||
parser.add_argument('--path', type=Path, required=True)
|
||||
parser.add_argument('--flashbang', choices=('true', 'false'), required=True)
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
print(filter_flashbang(args.path) if args.flashbang == 'false' else args.path.read_text(encoding='utf-8-sig'), end='')
|
||||
except (OSError, ValueError, KeyError) as error:
|
||||
print(f'Install options: {error}', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
read_install_boolean() {
|
||||
local prompt=$1 default=$2 hint=y/N answer
|
||||
[ "$default" = false ] || hint=Y/n
|
||||
while :; do
|
||||
printf '%s [%s] ' "$prompt" "$hint" >&2
|
||||
IFS= read -r answer || { printf 'Input ended before install options were confirmed.\n' >&2; return 1; }
|
||||
answer=${answer%$'\r'}
|
||||
case "$answer" in
|
||||
'') printf '%s\n' "$default"; return ;;
|
||||
y|Y|yes|Yes|YES) printf 'true\n'; return ;;
|
||||
n|N|no|No|NO) printf 'false\n'; return ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
read_install_options() {
|
||||
update_agents=false
|
||||
flashbang=true
|
||||
local saved key value
|
||||
if [ -f "$home_path/.my-ai-configuration/selection.json" ]; then
|
||||
if saved=$(python3 "$root/scripts/lib/selection-state.py" read --home "$home_path" --manifest "$root/adapters/plugins.tsv" --format tsv --allow-legacy); then
|
||||
while IFS=$'\t' read -r key value; do
|
||||
value=${value%$'\r'}
|
||||
case "$key" in update_agents) update_agents=$value ;; flashbang) flashbang=$value ;; esac
|
||||
done <<< "$saved"
|
||||
else
|
||||
printf 'WARN Saved options could not be read; confirm new options below.\n' >&2
|
||||
fi
|
||||
fi
|
||||
[ "$dry_run" = false ] || return 0
|
||||
update_agents=$(read_install_boolean "Update selected agent CLIs ($client)?" "$update_agents") || return
|
||||
flashbang=$(read_install_boolean 'Enable the Flashbang notification hook?' "$flashbang") || return
|
||||
}
|
||||
|
||||
is_windows_host() {
|
||||
case "${OSTYPE:-}" in msys*|cygwin*|win32*) return 0 ;; *) return 1 ;; esac
|
||||
}
|
||||
|
||||
codex_process_active() {
|
||||
is_windows_host || return 1
|
||||
command -v powershell.exe >/dev/null 2>&1 || return 1
|
||||
powershell.exe -NoProfile -Command "if (Get-Process -Name codex -ErrorAction SilentlyContinue) { exit 0 }; exit 1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
global_npm_codex() {
|
||||
command -v npm >/dev/null 2>&1 || return 1
|
||||
npm list -g '@openai/codex' --depth=0 --json >/dev/null 2>&1
|
||||
}
|
||||
|
||||
update_selected_agent_clis() {
|
||||
local selected_client clients=()
|
||||
case "$client" in codex|both) clients+=(codex) ;; esac
|
||||
case "$client" in claude|both) clients+=(claude) ;; esac
|
||||
for selected_client in "${clients[@]}"; do
|
||||
if [ "$selected_client" = codex ] && [ "$dry_run" = false ] && codex_process_active; then
|
||||
printf 'WARN Codex CLI update skipped because codex.exe is running. Close all Codex sessions and run the update again to update the CLI.\n' >&2
|
||||
continue
|
||||
fi
|
||||
if [ "$selected_client" = codex ] && global_npm_codex; then
|
||||
CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE=1 CI=true run_plugin_command "$dry_run" npm install -g '@openai/codex@latest' </dev/null || return
|
||||
else
|
||||
CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE=1 CI=true run_plugin_command "$dry_run" "$selected_client" update </dev/null || return
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -11,7 +11,7 @@ function Get-Sha256Hash {
|
||||
}
|
||||
|
||||
function Get-Sha256HashOfBytes {
|
||||
param([Parameter(Mandatory=$true)][byte[]]$Bytes)
|
||||
param([Parameter(Mandatory=$true)][AllowEmptyCollection()][byte[]]$Bytes)
|
||||
$sha256 = [System.Security.Cryptography.SHA256]::Create()
|
||||
try { return ([System.BitConverter]::ToString($sha256.ComputeHash($Bytes))).Replace('-', '').ToLowerInvariant() }
|
||||
finally { $sha256.Dispose() }
|
||||
@@ -55,7 +55,8 @@ function Sync-ManagedDestination {
|
||||
[Parameter(Mandatory=$true)][string]$Stamp,
|
||||
[string]$AiConfigRoot,
|
||||
[string]$ShellCommand,
|
||||
[string]$WindowsShellCommand,
|
||||
[string]$PowerShellCommand,
|
||||
[bool]$FlashbangEnabled = $true,
|
||||
[switch]$DryRun,
|
||||
[switch]$Summary
|
||||
)
|
||||
@@ -69,10 +70,15 @@ function Sync-ManagedDestination {
|
||||
Get-ChildItem $Source -File -Recurse | ForEach-Object {
|
||||
$relative = $_.FullName.Substring($Source.Length).TrimStart([char[]]@('\','/')).Replace('\','/')
|
||||
$target = Join-Path $Destination $relative
|
||||
$rawContent = Get-Content -LiteralPath $_.FullName -Raw
|
||||
$needsSubstitution = $rawContent.Contains('__AI_CONFIG_ROOT__') -or $rawContent.Contains('__HOOK_COMMAND__') -or $rawContent.Contains('__WINDOWS_HOOK_COMMAND__')
|
||||
$rawContent = Get-Content -LiteralPath $_.FullName -Raw -Encoding UTF8
|
||||
$filterFlashbang = -not $FlashbangEnabled -and $relative -in @('settings.json', 'config.toml')
|
||||
if ($filterFlashbang) {
|
||||
$rawContent = (& python (Join-Path $PSScriptRoot 'install-options.py') filter --path $_.FullName --flashbang false | Out-String)
|
||||
if ($LASTEXITCODE -ne 0) { throw 'Could not configure Flashbang.' }
|
||||
}
|
||||
$needsSubstitution = $filterFlashbang -or $rawContent.Contains('__AI_CONFIG_ROOT__') -or $rawContent.Contains('__HOOK_COMMAND__') -or $rawContent.Contains('__POWERSHELL_HOOK_COMMAND__') -or $rawContent.Contains('__POWERSHELL_COMMAND__')
|
||||
if ($needsSubstitution) {
|
||||
$finalContent = $rawContent.Replace('__AI_CONFIG_ROOT__', $AiConfigRoot).Replace('__HOOK_COMMAND__', $ShellCommand).Replace('__WINDOWS_HOOK_COMMAND__', $WindowsShellCommand).Replace('__HOOK_SCRIPT__', 'flashbang.ps1').Replace('__WINDOWS_HOOK_SCRIPT__', 'flashbang.ps1')
|
||||
$finalContent = $rawContent.Replace('__AI_CONFIG_ROOT__', $AiConfigRoot).Replace('__HOOK_COMMAND__', $ShellCommand).Replace('__POWERSHELL_HOOK_COMMAND__', $PowerShellCommand).Replace('__POWERSHELL_COMMAND__', $PowerShellCommand).Replace('__HOOK_SCRIPT__', 'flashbang.ps1').Replace('__POWERSHELL_HOOK_SCRIPT__', 'flashbang.ps1')
|
||||
$newBytes = [System.Text.Encoding]::UTF8.GetBytes($finalContent)
|
||||
} else {
|
||||
$newBytes = [System.IO.File]::ReadAllBytes($_.FullName)
|
||||
|
||||
+10
-5
@@ -49,9 +49,9 @@ write_managed_manifest() {
|
||||
} > "$path"
|
||||
}
|
||||
|
||||
# sync_managed_destination <source-dir> <destination-dir> <stamp> <ai-config-root> <shell-command> <windows-shell-command> <dry-run: true|false> [summary: true|false]
|
||||
# sync_managed_destination <source-dir> <destination-dir> <stamp> <ai-config-root> <shell-command> <powershell-command> <dry-run: true|false> [summary: true|false]
|
||||
sync_managed_destination() {
|
||||
local source=$1 destination=$2 stamp=$3 ai_config_root=$4 shell_command=$5 windows_shell_command=$6 dry_run=$7 summary=${8:-false}
|
||||
local source=$1 destination=$2 stamp=$3 ai_config_root=$4 shell_command=$5 powershell_command=$6 dry_run=$7 summary=${8:-false} flashbang_enabled=${9:-true}
|
||||
[ "$summary" = true ] || printf 'SOURCE %s -> %s\n' "$source" "$destination"
|
||||
local manifest
|
||||
manifest=$(manifest_path "$destination")
|
||||
@@ -67,13 +67,18 @@ sync_managed_destination() {
|
||||
target="$destination/$relative"
|
||||
content=$(<"$source_file")
|
||||
needs_sub=false
|
||||
if [[ "$content" == *'__AI_CONFIG_ROOT__'* || "$content" == *'__HOOK_COMMAND__'* || "$content" == *'__WINDOWS_HOOK_COMMAND__'* ]]; then
|
||||
if [ "$flashbang_enabled" = false ] && [[ "$relative" = settings.json || "$relative" = config.toml ]]; then
|
||||
content=$(python3 "$(dirname -- "${BASH_SOURCE[0]}")/install-options.py" filter --path "$source_file" --flashbang false) || return
|
||||
needs_sub=true
|
||||
fi
|
||||
if [[ "$needs_sub" = true || "$content" == *'__AI_CONFIG_ROOT__'* || "$content" == *'__HOOK_COMMAND__'* || "$content" == *'__POWERSHELL_HOOK_COMMAND__'* || "$content" == *'__POWERSHELL_COMMAND__'* ]]; then
|
||||
needs_sub=true
|
||||
content=${content//__AI_CONFIG_ROOT__/$ai_config_root}
|
||||
content=${content//__HOOK_COMMAND__/$shell_command}
|
||||
content=${content//__WINDOWS_HOOK_COMMAND__/$windows_shell_command}
|
||||
content=${content//__POWERSHELL_HOOK_COMMAND__/$powershell_command}
|
||||
content=${content//__POWERSHELL_COMMAND__/$powershell_command}
|
||||
content=${content//__HOOK_SCRIPT__/flashbang.sh}
|
||||
content=${content//__WINDOWS_HOOK_SCRIPT__/flashbang.sh}
|
||||
content=${content//__POWERSHELL_HOOK_SCRIPT__/flashbang.sh}
|
||||
new_hash=$(sha256_of_string "$content")
|
||||
else
|
||||
new_hash=$(sha256_of_file "$source_file")
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
function Read-UpdateSelection {
|
||||
param([string]$HomePath, [string]$RepositoryRoot)
|
||||
$output = & python (Join-Path $PSScriptRoot 'selection-state.py') read --home $HomePath --manifest (Join-Path $RepositoryRoot 'adapters/plugins.tsv')
|
||||
param([string]$HomePath, [string]$RepositoryRoot, [switch]$AllowLegacy)
|
||||
$arguments = @((Join-Path $PSScriptRoot 'selection-state.py'), 'read', '--home', $HomePath, '--manifest', (Join-Path $RepositoryRoot 'adapters/plugins.tsv'))
|
||||
if ($AllowLegacy) { $arguments += '--allow-legacy' }
|
||||
$output = & python @arguments
|
||||
if ($LASTEXITCODE -ne 0) { throw 'Could not load the saved selection.' }
|
||||
return ($output | Out-String | ConvertFrom-Json)
|
||||
}
|
||||
|
||||
function Save-UpdateSelection {
|
||||
param([string]$HomePath, [string]$RepositoryRoot, [string]$Platform, [string]$Client, [hashtable]$Plugins)
|
||||
$arguments = @((Join-Path $PSScriptRoot 'selection-state.py'), 'write', '--home', $HomePath, '--manifest', (Join-Path $RepositoryRoot 'adapters/plugins.tsv'), '--platform', $Platform.ToLowerInvariant(), '--client', $Client.ToLowerInvariant(), '--selected')
|
||||
param([string]$HomePath, [string]$RepositoryRoot, [string]$Shell, [string]$Client, [hashtable]$Plugins,
|
||||
[Parameter(Mandatory=$true)][bool]$UpdateAgents, [Parameter(Mandatory=$true)][bool]$Flashbang)
|
||||
$arguments = @((Join-Path $PSScriptRoot 'selection-state.py'), 'write', '--home', $HomePath, '--manifest', (Join-Path $RepositoryRoot 'adapters/plugins.tsv'), '--shell', $Shell.ToLowerInvariant(), '--client', $Client.ToLowerInvariant(), '--update-agents', $UpdateAgents.ToString().ToLowerInvariant(), '--flashbang', $Flashbang.ToString().ToLowerInvariant(), '--selected')
|
||||
$arguments += @($Plugins.Selected | ForEach-Object { $_.name })
|
||||
$arguments += '--deselected'
|
||||
$arguments += @($Plugins.Deselected | ForEach-Object { $_.name })
|
||||
|
||||
@@ -7,11 +7,19 @@ import sys
|
||||
import tempfile
|
||||
|
||||
|
||||
def validate(state):
|
||||
if not isinstance(state, dict) or state.get('version') != 1:
|
||||
def validate(state, allow_legacy=False):
|
||||
if isinstance(state, dict) and state.get('version') == 1:
|
||||
if not allow_legacy:
|
||||
raise ValueError('Saved selection predates install options. Run update once without Quick.')
|
||||
state = dict(state, version=2, shell={'windows': 'powershell', 'linux': 'bash'}.get(state.get('platform')),
|
||||
update_agents=False, flashbang=True)
|
||||
state.pop('platform', None)
|
||||
if not isinstance(state, dict) or state.get('version') != 2:
|
||||
raise ValueError('Unsupported saved selection.')
|
||||
if state.get('platform') not in ('windows', 'linux') or state.get('client') not in ('codex', 'claude', 'both'):
|
||||
raise ValueError('Invalid saved platform or client.')
|
||||
if state.get('shell') not in ('powershell', 'bash') or state.get('client') not in ('codex', 'claude', 'both'):
|
||||
raise ValueError('Invalid saved shell or client.')
|
||||
if any(type(state.get(key)) is not bool for key in ('update_agents', 'flashbang')):
|
||||
raise ValueError('Invalid saved install options. Run update once without Quick.')
|
||||
for key in ('selected', 'deselected'):
|
||||
values = state.get(key)
|
||||
if not isinstance(values, list) or any(not isinstance(value, str) or not value or any(ord(c) < 32 for c in value) for value in values):
|
||||
@@ -29,7 +37,10 @@ def main():
|
||||
parser.add_argument('--home', required=True)
|
||||
parser.add_argument('--manifest', required=True)
|
||||
parser.add_argument('--format', choices=('json', 'tsv'), default='json')
|
||||
parser.add_argument('--platform')
|
||||
parser.add_argument('--shell')
|
||||
parser.add_argument('--allow-legacy', action='store_true')
|
||||
parser.add_argument('--update-agents', choices=('true', 'false'))
|
||||
parser.add_argument('--flashbang', choices=('true', 'false'))
|
||||
parser.add_argument('--client')
|
||||
parser.add_argument('--selected', nargs='*', default=[])
|
||||
parser.add_argument('--deselected', nargs='*', default=[])
|
||||
@@ -40,19 +51,23 @@ def main():
|
||||
if args.action == 'read':
|
||||
if not path.is_file():
|
||||
raise ValueError('No saved selection. Run install or update once without Quick.')
|
||||
state = validate(json.loads(path.read_text(encoding='utf-8-sig')))
|
||||
state = validate(json.loads(path.read_text(encoding='utf-8-sig')), args.allow_legacy)
|
||||
for key in ('selected', 'deselected'):
|
||||
state[key] = [name for name in state[key] if name in names]
|
||||
if args.format == 'json':
|
||||
print(json.dumps(state))
|
||||
else:
|
||||
print('platform\t' + state['platform'])
|
||||
print('shell\t' + state['shell'])
|
||||
print('client\t' + state['client'])
|
||||
for key in ('update_agents', 'flashbang'):
|
||||
print(key + '\t' + str(state[key]).lower())
|
||||
for key in ('selected', 'deselected'):
|
||||
for name in state[key]:
|
||||
print(key + '\t' + name)
|
||||
return
|
||||
state = validate(dict(version=1, platform=args.platform, client=args.client,
|
||||
state = validate(dict(version=2, shell=args.shell, client=args.client,
|
||||
update_agents=None if args.update_agents is None else args.update_agents == 'true',
|
||||
flashbang=None if args.flashbang is None else args.flashbang == 'true',
|
||||
selected=args.selected, deselected=args.deselected))
|
||||
if (set(state['selected']) | set(state['deselected'])) - names:
|
||||
raise ValueError('Unknown plugin in selection.')
|
||||
|
||||
@@ -8,8 +8,10 @@ read_update_selection() {
|
||||
while IFS=$'\t' read -r key value; do
|
||||
value=${value%$'\r'}
|
||||
case "$key" in
|
||||
platform) [ -n "$platform" ] || platform=$value ;;
|
||||
shell) [ -n "$shell" ] || shell=$value ;;
|
||||
client) [ -n "$client" ] || client=$value ;;
|
||||
update_agents) update_agents=$value ;;
|
||||
flashbang) flashbang=$value ;;
|
||||
selected) selected_plugins+=("$value") ;;
|
||||
deselected) deselected_plugins+=("$value") ;;
|
||||
esac
|
||||
@@ -18,5 +20,6 @@ read_update_selection() {
|
||||
|
||||
save_update_selection() {
|
||||
python3 "$root/scripts/lib/selection-state.py" write --home "$home_path" --manifest "$root/adapters/plugins.tsv" \
|
||||
--platform "$platform" --client "$client" --selected "${selected_plugins[@]}" --deselected "${deselected_plugins[@]}"
|
||||
--shell "$shell" --client "$client" --update-agents "$update_agents" --flashbang "$flashbang" \
|
||||
--selected "${selected_plugins[@]}" --deselected "${deselected_plugins[@]}"
|
||||
}
|
||||
Reference in new issue
Block a user