Reshape the agent launcher into omarchy agent (#6757)
* Reshape the agent launcher into omarchy agent omarchy-launch-agent becomes omarchy-agent, with prompts on omarchy-agent-prompt rather than the bare route: `omarchy agent` is both a command and a group, so a positional prompt there would shadow any subcommand under it. The launcher takes flags only and points at `omarchy agent prompt` when handed one. Every agent window now launches under a fixed org.omarchy.agent app-id instead of omarchy-launch-tui's default of org.omarchy.<binary>, so one rule floats them all whichever agent is default. Omarchy also stops picking an agent for you. omarchy-default-agent prints nothing until one is chosen, leaving every entry under Setup > Defaults > Agent unchecked, and a first-run invitation offers to take you there. * Wordsmith * Cover the agent routes and the invitation The route split is the point of the change, so exercise `omarchy agent`, `omarchy agent prompt`, and a rejected positional prompt through the router rather than only the binaries behind them. The invitation gets the same treatment as the Voxtype and fingerprint ones: it notifies once, opens the agent defaults menu, and leaves both the notification and the marker alone for anyone who already chose an agent. * Offer the agent choice from the keybinding Super + Shift + Ctrl + A now runs `omarchy-agent --pick`, which opens Setup > Defaults > Agent when nothing is chosen yet. A keypress that writes to stderr and opens nothing just looks broken. * Reach existing installs with the agent invitation first-run installs the invitation hook, and existing accounts marked it complete long ago, so they would never see it -- while being the accounts most likely to need it, since the old getter returned opencode implicitly and most have no agent recorded at all. Post-update hooks run later in the same update, so the invitation arrives without waiting for another one. * Say what the Defaults submenus set Setup > Defaults lists Agent, Browser, Terminal, Editor, but the header inside each repeated the same bare word, which reads as a category rather than a setting -- and says nothing at all when the menu is summoned straight into it. The list keeps its short labels; the headers now name the setting.
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
|
||||
source "$(dirname "$0")/base-test.sh"
|
||||
|
||||
test_home=$(mktemp -d)
|
||||
test_bin=$(mktemp -d)
|
||||
log_file=$(mktemp)
|
||||
hook_path="$test_home/.config/omarchy/hooks/post-update.d/setup-agent.hook"
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$test_home" "$test_bin"
|
||||
rm -f "$log_file"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
mkdir -p "$(dirname "$hook_path")"
|
||||
|
||||
cat >"$test_bin/omarchy-notification-send" <<'EOF'
|
||||
#!/bin/bash
|
||||
echo notification >>"$TEST_LOG"
|
||||
while (($# > 0)); do
|
||||
[[ $1 == "--exec" ]] && echo "exec:$2" >>"$TEST_LOG"
|
||||
shift
|
||||
done
|
||||
EOF
|
||||
chmod +x "$test_bin/omarchy-notification-send"
|
||||
|
||||
run_invitation_hook() {
|
||||
cp "$ROOT/install/user/first-run/setup-agent.hook" "$hook_path"
|
||||
HOME="$test_home" PATH="$test_bin:$ROOT/bin:$PATH" TEST_LOG="$log_file" bash "$hook_path"
|
||||
}
|
||||
|
||||
run_invitation_hook
|
||||
|
||||
[[ -f $test_home/.local/state/omarchy/done/agent-setup-invitation ]] || fail "agent invitation records completion"
|
||||
[[ -f $hook_path ]] || fail "agent invitation keeps its hook installed"
|
||||
[[ $(grep -c '^notification$' "$log_file") -eq 1 ]] || fail "agent invitation sends one notification"
|
||||
grep -qx 'exec:omarchy menu summon setup.default.agent' "$log_file" ||
|
||||
fail "agent invitation opens the agent defaults menu"
|
||||
|
||||
run_invitation_hook
|
||||
[[ $(grep -c '^notification$' "$log_file") -eq 1 ]] || fail "completed agent invitation does not notify again"
|
||||
|
||||
pass "agent invitation only runs once"
|
||||
|
||||
# Someone who already chose an agent has nothing to be invited to, and must not
|
||||
# burn the marker either -- otherwise clearing the choice later leaves them with
|
||||
# no invitation and no default.
|
||||
fresh_home=$(mktemp -d)
|
||||
mkdir -p "$fresh_home/.config/omarchy/defaults"
|
||||
printf 'claude\n' >"$fresh_home/.config/omarchy/defaults/agent"
|
||||
: >"$log_file"
|
||||
cp "$ROOT/install/user/first-run/setup-agent.hook" "$hook_path"
|
||||
HOME="$fresh_home" PATH="$test_bin:$ROOT/bin:$PATH" TEST_LOG="$log_file" bash "$hook_path"
|
||||
|
||||
[[ ! -s $log_file ]] || fail "agent invitation stays quiet when a default is already set"
|
||||
[[ ! -f $fresh_home/.local/state/omarchy/done/agent-setup-invitation ]] ||
|
||||
fail "agent invitation leaves its marker unset when a default is already set"
|
||||
rm -rf "$fresh_home"
|
||||
|
||||
pass "agent invitation skips anyone who already chose an agent"
|
||||
@@ -18,6 +18,7 @@ mise_log="$test_tmp/mise"
|
||||
mise_history="$test_tmp/mise-history"
|
||||
stub_log="$test_tmp/stubs"
|
||||
terminal_log="$test_tmp/terminal"
|
||||
menu_log="$test_tmp/menu"
|
||||
mkdir -p "$mock_bin" "$test_home"
|
||||
|
||||
cat >"$mock_bin/omarchy-notification-send" <<'SH'
|
||||
@@ -63,6 +64,11 @@ fi
|
||||
[[ ${OMARCHY_TEST_MISE_FAIL:-false} != "true" ]]
|
||||
SH
|
||||
|
||||
cat >"$mock_bin/omarchy-menu" <<'SH'
|
||||
#!/bin/bash
|
||||
printf '%s\0' "$@" >"$OMARCHY_TEST_AGENT_MENU_LOG"
|
||||
SH
|
||||
|
||||
cat >"$mock_bin/omarchy-test-noop" <<'SH'
|
||||
#!/bin/bash
|
||||
exit 0
|
||||
@@ -84,6 +90,7 @@ export OMARCHY_TEST_MISE_LOG="$mise_log"
|
||||
export OMARCHY_TEST_MISE_HISTORY="$mise_history"
|
||||
export OMARCHY_TEST_STUB_LOG="$stub_log"
|
||||
export OMARCHY_TEST_AGENT_TERMINAL_LOG="$terminal_log"
|
||||
export OMARCHY_TEST_AGENT_MENU_LOG="$menu_log"
|
||||
|
||||
grok_package="npm:@xai-official/grok"
|
||||
omp_package="github:can1357/oh-my-pi"
|
||||
@@ -140,30 +147,44 @@ for command in omp grok crush; do
|
||||
done
|
||||
pass "Remove Preinstalls deletes every optional agent lazy stub"
|
||||
|
||||
[[ $(omarchy-default-agent) == "opencode" ]] || fail "default agent falls back to OpenCode"
|
||||
pass "default agent falls back to OpenCode"
|
||||
[[ -z $(omarchy-default-agent) ]] || fail "default agent is unset until one is chosen"
|
||||
pass "default agent is unset until one is chosen"
|
||||
|
||||
omarchy-launch-agent
|
||||
mapfile -d '' -t launch_args <"$launch_log"
|
||||
[[ ${launch_args[*]} == "opencode --auto" ]] ||
|
||||
fail "agent launcher falls back to OpenCode before a default is selected"
|
||||
pass "agent launcher falls back to OpenCode before a default is selected"
|
||||
: >"$launch_log"
|
||||
if omarchy-agent >"$test_tmp/no-agent-output" 2>&1; then
|
||||
fail "agent launcher refuses to launch without a default"
|
||||
fi
|
||||
grep -Fq "Choose default agent with" "$test_tmp/no-agent-output" ||
|
||||
fail "agent launcher explains that no default is set"
|
||||
[[ ! -s $launch_log ]] || fail "agent launcher starts nothing without a default"
|
||||
pass "agent launcher refuses to launch without a default"
|
||||
|
||||
# The keybinding uses --pick, where an error on stderr nobody sees would make
|
||||
# the keypress look broken. It offers the choice instead.
|
||||
: >"$launch_log"
|
||||
: >"$menu_log"
|
||||
omarchy-agent --pick
|
||||
mapfile -d '' -t menu_args <"$menu_log"
|
||||
[[ ${menu_args[*]} == "summon setup.default.agent" ]] ||
|
||||
fail "--pick opens the agent defaults menu when none is set"
|
||||
[[ ! -s $launch_log ]] || fail "--pick starts nothing when no agent is set"
|
||||
pass "--pick opens the agent defaults menu when none is set"
|
||||
|
||||
source "$ROOT/default/bash/aliases"
|
||||
[[ $(alias a) == "alias a='omarchy-launch-agent --inline'" ]] ||
|
||||
[[ $(alias a) == "alias a='omarchy-agent --inline'" ]] ||
|
||||
fail "terminal alias launches the default agent inline"
|
||||
pass "terminal alias launches the default agent inline"
|
||||
|
||||
grep -Fq 'o.bind("SUPER + SHIFT + CTRL + A", "Agent", "omarchy-launch-agent")' \
|
||||
grep -Fq 'o.bind("SUPER + SHIFT + CTRL + A", "Agent", "omarchy-agent --pick")' \
|
||||
"$ROOT/default/hypr/bindings/utilities.lua" ||
|
||||
fail "agent launcher has a keyboard shortcut"
|
||||
pass "agent launcher has a keyboard shortcut"
|
||||
|
||||
cat >"$mock_bin/omarchy-launch-agent" <<'SH'
|
||||
cat >"$mock_bin/omarchy-agent" <<'SH'
|
||||
#!/bin/bash
|
||||
printf '%s\0' omarchy-launch-agent "$@" >"$OMARCHY_TEST_AGENT_OPEN_LOG"
|
||||
printf '%s\0' omarchy-agent "$@" >"$OMARCHY_TEST_AGENT_OPEN_LOG"
|
||||
SH
|
||||
chmod +x "$mock_bin/omarchy-launch-agent"
|
||||
chmod +x "$mock_bin/omarchy-agent"
|
||||
hash -r
|
||||
|
||||
declare -A expected_agents=(
|
||||
@@ -206,7 +227,7 @@ for selection in "${!expected_agents[@]}"; do
|
||||
fail "default agent installs $selection globally through mise"
|
||||
|
||||
mapfile -d '' -t agent_open_args <"$agent_open_log"
|
||||
[[ ${#agent_open_args[@]} == 1 && ${agent_open_args[0]} == "omarchy-launch-agent" ]] ||
|
||||
[[ ${#agent_open_args[@]} == 1 && ${agent_open_args[0]} == "omarchy-agent" ]] ||
|
||||
fail "default agent opens $selection after selecting it"
|
||||
done
|
||||
pass "default agent selects and opens every supported provider and alias"
|
||||
@@ -235,7 +256,7 @@ mapfile -d '' -t mise_args <"$mise_log"
|
||||
[[ $(<"$test_tmp/install-output") == $'\033[2J\033[3J\033[H' ]] ||
|
||||
fail "visible agent installation clears its terminal before opening the agent"
|
||||
mapfile -d '' -t agent_open_args <"$agent_open_log"
|
||||
[[ ${#agent_open_args[@]} == 2 && ${agent_open_args[0]} == "omarchy-launch-agent" && ${agent_open_args[1]} == "--inline" ]] ||
|
||||
[[ ${#agent_open_args[@]} == 2 && ${agent_open_args[0]} == "omarchy-agent" && ${agent_open_args[1]} == "--inline" ]] ||
|
||||
fail "newly installed agent opens in the installation terminal"
|
||||
pass "missing agents install visibly and open in the same terminal"
|
||||
|
||||
@@ -249,7 +270,7 @@ mapfile -d '' -t mise_args <"$mise_log"
|
||||
[[ ${mise_args[0]} == "use" && ${mise_args[1]} == "-g" && ${mise_args[2]} == "copilot" ]] ||
|
||||
fail "default agent still activates an installed provider globally through mise"
|
||||
mapfile -d '' -t agent_open_args <"$agent_open_log"
|
||||
[[ ${#agent_open_args[@]} == 1 && ${agent_open_args[0]} == "omarchy-launch-agent" ]] ||
|
||||
[[ ${#agent_open_args[@]} == 1 && ${agent_open_args[0]} == "omarchy-agent" ]] ||
|
||||
fail "installed agent opens in a new terminal after selection"
|
||||
pass "installed agents select and open without notifications"
|
||||
|
||||
@@ -287,14 +308,16 @@ grep -F "Could not set Codex as the default coding agent" "$test_tmp/setup-failu
|
||||
[[ ! -s $agent_open_log ]] || fail "failed activation does not open an agent"
|
||||
pass "default agent reports mise failures without notifications"
|
||||
|
||||
rm "$mock_bin/omarchy-launch-agent"
|
||||
rm "$mock_bin/omarchy-agent"
|
||||
hash -r
|
||||
|
||||
assert_launched() {
|
||||
local agent=$1
|
||||
local description=$2
|
||||
shift 2
|
||||
local expected=("$@")
|
||||
# Every agent window launches under the same app-id, whichever agent is
|
||||
# default, so default/hypr/apps/agent.lua can float them all.
|
||||
local expected=(--app-id=org.omarchy.agent "$@")
|
||||
|
||||
mapfile -d '' -t actual <"$launch_log"
|
||||
|
||||
@@ -312,7 +335,7 @@ assert_launch() {
|
||||
shift
|
||||
|
||||
printf '%s\n' "$agent" >"$agent_file"
|
||||
omarchy-launch-agent "Review this" project
|
||||
omarchy-agent-prompt "Review this" project
|
||||
assert_launched "$agent" "forwards the interactive prompt" "$@"
|
||||
}
|
||||
|
||||
@@ -321,7 +344,7 @@ assert_bypass() {
|
||||
shift
|
||||
|
||||
printf '%s\n' "$agent" >"$agent_file"
|
||||
omarchy-launch-agent
|
||||
omarchy-agent
|
||||
assert_launched "$agent" "skips permission prompts" "$@"
|
||||
}
|
||||
|
||||
@@ -348,20 +371,53 @@ assert_bypass copilot copilot --allow-all
|
||||
pass "agent launcher skips permission prompts for every supported agent"
|
||||
|
||||
printf '%s\n' "opencode" >"$agent_file"
|
||||
omarchy-launch-agent
|
||||
omarchy-agent
|
||||
mapfile -d '' -t launch_args <"$launch_log"
|
||||
[[ ${launch_args[*]} == "opencode --auto" ]] ||
|
||||
[[ ${launch_args[*]} == "--app-id=org.omarchy.agent opencode --auto" ]] ||
|
||||
fail "agent launcher starts the selected agent without an initial prompt"
|
||||
pass "agent launcher starts the selected agent without an initial prompt"
|
||||
|
||||
omarchy-launch-agent --inline "Review this project"
|
||||
omarchy-agent-prompt --inline "Review this project"
|
||||
mapfile -d '' -t inline_args <"$inline_log"
|
||||
[[ ${inline_args[*]} == "opencode --auto --prompt Review this project" ]] ||
|
||||
fail "inline agent launcher runs in the current terminal"
|
||||
pass "inline agent launcher runs in the current terminal"
|
||||
|
||||
# The prompt route exists so the router can tell a prompt from a subcommand, so
|
||||
# cover the public routes and not only the binaries behind them.
|
||||
: >"$launch_log"
|
||||
omarchy agent
|
||||
mapfile -d '' -t launch_args <"$launch_log"
|
||||
[[ ${launch_args[*]} == "--app-id=org.omarchy.agent opencode --auto" ]] ||
|
||||
fail "omarchy agent routes to the launcher"
|
||||
|
||||
# With an agent chosen there is nothing to pick, so the keybinding launches.
|
||||
: >"$launch_log"
|
||||
: >"$menu_log"
|
||||
omarchy-agent --pick
|
||||
mapfile -d '' -t launch_args <"$launch_log"
|
||||
[[ ${launch_args[*]} == "--app-id=org.omarchy.agent opencode --auto" ]] ||
|
||||
fail "--pick launches once an agent is chosen"
|
||||
[[ ! -s $menu_log ]] || fail "--pick opens no menu once an agent is chosen"
|
||||
pass "--pick launches once an agent is chosen"
|
||||
|
||||
: >"$launch_log"
|
||||
omarchy agent prompt "Review this project"
|
||||
mapfile -d '' -t launch_args <"$launch_log"
|
||||
[[ ${launch_args[*]} == "--app-id=org.omarchy.agent opencode --auto --prompt Review this project" ]] ||
|
||||
fail "omarchy agent prompt routes the prompt to the launcher"
|
||||
|
||||
: >"$launch_log"
|
||||
if omarchy agent Review this project >"$test_tmp/positional-output" 2>&1; then
|
||||
fail "omarchy agent rejects a positional prompt"
|
||||
fi
|
||||
grep -F "omarchy agent prompt" "$test_tmp/positional-output" >/dev/null ||
|
||||
fail "omarchy agent points a positional prompt at the prompt route"
|
||||
[[ ! -s $launch_log ]] || fail "omarchy agent starts nothing for a positional prompt"
|
||||
pass "omarchy agent keeps prompts on the prompt route"
|
||||
|
||||
printf '%s\n' "missing" >"$agent_file"
|
||||
if OMARCHY_TEST_MISSING_COMMAND=missing omarchy-launch-agent >"$test_tmp/missing-output" 2>&1; then
|
||||
if OMARCHY_TEST_MISSING_COMMAND=missing omarchy-agent >"$test_tmp/missing-output" 2>&1; then
|
||||
fail "agent launcher rejects a missing default command"
|
||||
fi
|
||||
grep -F "missing is not installed" "$test_tmp/missing-output" >/dev/null ||
|
||||
|
||||
Reference in New Issue
Block a user