feat(selection): persist retrieval preference
This commit is contained in:
1 parent
151306a6cc
commit
bfbe001248
7 files changed
+24
-8
No files matched your search
@@ -15,7 +15,7 @@ function Read-InstallBoolean {
|
|||||||
|
|
||||||
function Read-InstallOptions {
|
function Read-InstallOptions {
|
||||||
param([string]$HomePath, [string]$RepositoryRoot, [string]$Client, [switch]$DryRun)
|
param([string]$HomePath, [string]$RepositoryRoot, [string]$Client, [switch]$DryRun)
|
||||||
$defaults = @{ update_agents = $false; flashbang = $true }
|
$defaults = @{ update_agents = $false; flashbang = $true; semantic_retrieval = $false }
|
||||||
if (Test-Path -LiteralPath (Join-Path $HomePath '.my-ai-configuration/selection.json')) {
|
if (Test-Path -LiteralPath (Join-Path $HomePath '.my-ai-configuration/selection.json')) {
|
||||||
try { $defaults = Read-UpdateSelection -HomePath $HomePath -RepositoryRoot $RepositoryRoot -AllowLegacy }
|
try { $defaults = Read-UpdateSelection -HomePath $HomePath -RepositoryRoot $RepositoryRoot -AllowLegacy }
|
||||||
catch { Write-Warning 'Saved options could not be read; confirm new options below.' }
|
catch { Write-Warning 'Saved options could not be read; confirm new options below.' }
|
||||||
@@ -24,6 +24,7 @@ function Read-InstallOptions {
|
|||||||
return @{
|
return @{
|
||||||
update_agents = Read-InstallBoolean -Prompt "Update selected agent CLIs ($Client)?" -Default $defaults.update_agents
|
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
|
flashbang = Read-InstallBoolean -Prompt 'Enable the Flashbang notification hook?' -Default $defaults.flashbang
|
||||||
|
semantic_retrieval = Read-InstallBoolean -Prompt 'Enable Qwen3-Embedding-0.6B semantic retrieval?' -Default $defaults.semantic_retrieval
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,13 @@ read_install_boolean() {
|
|||||||
read_install_options() {
|
read_install_options() {
|
||||||
update_agents=false
|
update_agents=false
|
||||||
flashbang=true
|
flashbang=true
|
||||||
|
semantic_retrieval=false
|
||||||
local saved key value
|
local saved key value
|
||||||
if [ -f "$home_path/.my-ai-configuration/selection.json" ]; then
|
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
|
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
|
while IFS=$'\t' read -r key value; do
|
||||||
value=${value%$'\r'}
|
value=${value%$'\r'}
|
||||||
case "$key" in update_agents) update_agents=$value ;; flashbang) flashbang=$value ;; esac
|
case "$key" in update_agents) update_agents=$value ;; flashbang) flashbang=$value ;; semantic_retrieval) semantic_retrieval=$value ;; esac
|
||||||
done <<< "$saved"
|
done <<< "$saved"
|
||||||
else
|
else
|
||||||
printf 'WARN Saved options could not be read; confirm new options below.\n' >&2
|
printf 'WARN Saved options could not be read; confirm new options below.\n' >&2
|
||||||
@@ -32,6 +33,7 @@ read_install_options() {
|
|||||||
[ "$dry_run" = false ] || return 0
|
[ "$dry_run" = false ] || return 0
|
||||||
update_agents=$(read_install_boolean "Update selected agent CLIs ($client)?" "$update_agents") || return
|
update_agents=$(read_install_boolean "Update selected agent CLIs ($client)?" "$update_agents") || return
|
||||||
flashbang=$(read_install_boolean 'Enable the Flashbang notification hook?' "$flashbang") || return
|
flashbang=$(read_install_boolean 'Enable the Flashbang notification hook?' "$flashbang") || return
|
||||||
|
semantic_retrieval=$(read_install_boolean 'Enable Qwen3-Embedding-0.6B semantic retrieval?' "$semantic_retrieval") || return
|
||||||
}
|
}
|
||||||
|
|
||||||
is_windows_host() {
|
is_windows_host() {
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ function Read-UpdateSelection {
|
|||||||
|
|
||||||
function Save-UpdateSelection {
|
function Save-UpdateSelection {
|
||||||
param([string]$HomePath, [string]$RepositoryRoot, [string]$Shell, [string]$Client, [hashtable]$Plugins,
|
param([string]$HomePath, [string]$RepositoryRoot, [string]$Shell, [string]$Client, [hashtable]$Plugins,
|
||||||
[Parameter(Mandatory=$true)][bool]$UpdateAgents, [Parameter(Mandatory=$true)][bool]$Flashbang)
|
[Parameter(Mandatory=$true)][bool]$UpdateAgents, [Parameter(Mandatory=$true)][bool]$Flashbang, [bool]$SemanticRetrieval = $false)
|
||||||
$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 = @((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(), '--semantic-retrieval', $SemanticRetrieval.ToString().ToLowerInvariant(), '--selected')
|
||||||
$arguments += @($Plugins.Selected | ForEach-Object { $_.name })
|
$arguments += @($Plugins.Selected | ForEach-Object { $_.name })
|
||||||
$arguments += '--deselected'
|
$arguments += '--deselected'
|
||||||
$arguments += @($Plugins.Deselected | ForEach-Object { $_.name })
|
$arguments += @($Plugins.Deselected | ForEach-Object { $_.name })
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ def validate(state, allow_legacy=False):
|
|||||||
raise ValueError('Unsupported saved selection.')
|
raise ValueError('Unsupported saved selection.')
|
||||||
if state.get('shell') not in ('powershell', 'bash') or state.get('client') not in ('codex', 'claude', 'both'):
|
if state.get('shell') not in ('powershell', 'bash') or state.get('client') not in ('codex', 'claude', 'both'):
|
||||||
raise ValueError('Invalid saved shell or client.')
|
raise ValueError('Invalid saved shell or client.')
|
||||||
if any(type(state.get(key)) is not bool for key in ('update_agents', 'flashbang')):
|
if 'semantic_retrieval' not in state:
|
||||||
|
state['semantic_retrieval'] = False
|
||||||
|
if any(type(state.get(key)) is not bool for key in ('update_agents', 'flashbang', 'semantic_retrieval')):
|
||||||
raise ValueError('Invalid saved install options. Run update once without Quick.')
|
raise ValueError('Invalid saved install options. Run update once without Quick.')
|
||||||
for key in ('selected', 'deselected'):
|
for key in ('selected', 'deselected'):
|
||||||
values = state.get(key)
|
values = state.get(key)
|
||||||
@@ -41,6 +43,7 @@ def main():
|
|||||||
parser.add_argument('--allow-legacy', action='store_true')
|
parser.add_argument('--allow-legacy', action='store_true')
|
||||||
parser.add_argument('--update-agents', choices=('true', 'false'))
|
parser.add_argument('--update-agents', choices=('true', 'false'))
|
||||||
parser.add_argument('--flashbang', choices=('true', 'false'))
|
parser.add_argument('--flashbang', choices=('true', 'false'))
|
||||||
|
parser.add_argument('--semantic-retrieval', choices=('true', 'false'))
|
||||||
parser.add_argument('--client')
|
parser.add_argument('--client')
|
||||||
parser.add_argument('--selected', nargs='*', default=[])
|
parser.add_argument('--selected', nargs='*', default=[])
|
||||||
parser.add_argument('--deselected', nargs='*', default=[])
|
parser.add_argument('--deselected', nargs='*', default=[])
|
||||||
@@ -59,7 +62,7 @@ def main():
|
|||||||
else:
|
else:
|
||||||
print('shell\t' + state['shell'])
|
print('shell\t' + state['shell'])
|
||||||
print('client\t' + state['client'])
|
print('client\t' + state['client'])
|
||||||
for key in ('update_agents', 'flashbang'):
|
for key in ('update_agents', 'flashbang', 'semantic_retrieval'):
|
||||||
print(key + '\t' + str(state[key]).lower())
|
print(key + '\t' + str(state[key]).lower())
|
||||||
for key in ('selected', 'deselected'):
|
for key in ('selected', 'deselected'):
|
||||||
for name in state[key]:
|
for name in state[key]:
|
||||||
@@ -68,6 +71,7 @@ def main():
|
|||||||
state = validate(dict(version=2, shell=args.shell, 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',
|
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',
|
flashbang=None if args.flashbang is None else args.flashbang == 'true',
|
||||||
|
semantic_retrieval=False if args.semantic_retrieval is None else args.semantic_retrieval == 'true',
|
||||||
selected=args.selected, deselected=args.deselected))
|
selected=args.selected, deselected=args.deselected))
|
||||||
if (set(state['selected']) | set(state['deselected'])) - names:
|
if (set(state['selected']) | set(state['deselected'])) - names:
|
||||||
raise ValueError('Unknown plugin in selection.')
|
raise ValueError('Unknown plugin in selection.')
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ read_update_selection() {
|
|||||||
client) [ -n "$client" ] || client=$value ;;
|
client) [ -n "$client" ] || client=$value ;;
|
||||||
update_agents) update_agents=$value ;;
|
update_agents) update_agents=$value ;;
|
||||||
flashbang) flashbang=$value ;;
|
flashbang) flashbang=$value ;;
|
||||||
|
semantic_retrieval) semantic_retrieval=$value ;;
|
||||||
selected) selected_plugins+=("$value") ;;
|
selected) selected_plugins+=("$value") ;;
|
||||||
deselected) deselected_plugins+=("$value") ;;
|
deselected) deselected_plugins+=("$value") ;;
|
||||||
esac
|
esac
|
||||||
@@ -20,6 +21,6 @@ read_update_selection() {
|
|||||||
|
|
||||||
save_update_selection() {
|
save_update_selection() {
|
||||||
python3 "$root/scripts/lib/selection-state.py" write --home "$home_path" --manifest "$root/adapters/plugins.tsv" \
|
python3 "$root/scripts/lib/selection-state.py" write --home "$home_path" --manifest "$root/adapters/plugins.tsv" \
|
||||||
--shell "$shell" --client "$client" --update-agents "$update_agents" --flashbang "$flashbang" \
|
--shell "$shell" --client "$client" --update-agents "$update_agents" --flashbang "$flashbang" --semantic-retrieval "${semantic_retrieval:-false}" \
|
||||||
--selected "${selected_plugins[@]}" --deselected "${deselected_plugins[@]}"
|
--selected "${selected_plugins[@]}" --deselected "${deselected_plugins[@]}"
|
||||||
}
|
}
|
||||||
@@ -184,7 +184,7 @@ class InstallOptionsTests(unittest.TestCase):
|
|||||||
'select_configured_plugins() { :; }\nsync_configured_plugins() { :; }\n'
|
'select_configured_plugins() { :; }\nsync_configured_plugins() { :; }\n'
|
||||||
'run_plugin_command() { printf "CLI-MOCK %s\\n" "$2"; }\n')
|
'run_plugin_command() { printf "CLI-MOCK %s\\n" "$2"; }\n')
|
||||||
environment = dict(os.environ, HOME=home.as_posix(), TEST_INSTALL_HOME=str(home))
|
environment = dict(os.environ, HOME=home.as_posix(), TEST_INSTALL_HOME=str(home))
|
||||||
for name, quick, answers in [('install', False, 'y\nn\n'), ('update', True, '')]:
|
for name, quick, answers in [('install', False, 'y\nn\nn\n'), ('update', True, '')]:
|
||||||
entry = str(scripts / (name + '.' + suffix))
|
entry = str(scripts / (name + '.' + suffix))
|
||||||
command = ([executable, '-NoProfile', '-File', entry, '-Shell', 'Bash', '-Client', 'Both', '-Summary']
|
command = ([executable, '-NoProfile', '-File', entry, '-Shell', 'Bash', '-Client', 'Both', '-Summary']
|
||||||
if kind == 'powershell' else [executable, entry, '--shell', 'bash', '--client', 'both', '--summary'])
|
if kind == 'powershell' else [executable, entry, '--shell', 'bash', '--client', 'both', '--summary'])
|
||||||
|
|||||||
@@ -71,6 +71,14 @@ class SelectionTests(unittest.TestCase):
|
|||||||
self.path.write_text(json.dumps(state))
|
self.path.write_text(json.dumps(state))
|
||||||
self.assertNotEqual(self.run_state('read').returncode, 0)
|
self.assertNotEqual(self.run_state('read').returncode, 0)
|
||||||
|
|
||||||
|
def test_semantic_retrieval_option_round_trips(self):
|
||||||
|
result = self.run_state('write', '--shell', 'bash', '--client', 'both', '--update-agents', 'false',
|
||||||
|
'--flashbang', 'true', '--semantic-retrieval', 'true')
|
||||||
|
self.assertEqual(result.returncode, 0, result.stderr)
|
||||||
|
state = json.loads(self.run_state('read').stdout)
|
||||||
|
self.assertTrue(state['semantic_retrieval'])
|
||||||
|
self.assertIn('semantic_retrieval\ttrue', self.run_state('read', '--format', 'tsv').stdout)
|
||||||
|
|
||||||
def test_invalid_write_preserves_last_selection(self):
|
def test_invalid_write_preserves_last_selection(self):
|
||||||
self.save('--selected', 'Superpowers')
|
self.save('--selected', 'Superpowers')
|
||||||
original = self.path.read_bytes()
|
original = self.path.read_bytes()
|
||||||
|
|||||||
Reference in new issue
Block a user