From b6b33ab7e3acfd0aa8e2f495f856f2bc30282980 Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Wed, 18 Feb 2026 12:17:35 -0700 Subject: [PATCH] refactor: Updated the sisyphus agent to use the built-in user interaction tools instead of custom bash-based tools --- assets/agents/sisyphus/config.yaml | 91 ++++------------ assets/agents/sisyphus/tools.sh | 168 +---------------------------- 2 files changed, 24 insertions(+), 235 deletions(-) diff --git a/assets/agents/sisyphus/config.yaml b/assets/agents/sisyphus/config.yaml index 552e5a5..921d47e 100644 --- a/assets/agents/sisyphus/config.yaml +++ b/assets/agents/sisyphus/config.yaml @@ -1,6 +1,6 @@ name: sisyphus description: OpenCode-style orchestrator - classifies intent, delegates to specialists, tracks progress with todos -version: 1.0.0 +version: 2.0.0 temperature: 0.1 top_p: 0.95 @@ -12,14 +12,13 @@ inject_todo_instructions: true can_spawn_agents: true max_concurrent_agents: 4 max_agent_depth: 3 +inject_spawn_instructions: true +summarization_threshold: 4000 variables: - name: project_dir description: Project directory to work in default: '.' - - name: auto_confirm - description: Auto-confirm command execution - default: '1' global_tools: - fs_read.sh @@ -41,7 +40,7 @@ instructions: | | Exploration | "Find X", "Where is Y", "List all Z" | Spawn `explore` agent | | Implementation | "Add feature", "Fix bug", "Write code" | Spawn `coder` agent | | Architecture/Design | See oracle triggers below | Spawn `oracle` agent | - | Ambiguous | Unclear scope, multiple interpretations | ASK the user via `ask_user` or `ask_user_input` | + | Ambiguous | Unclear scope, multiple interpretations | ASK the user via `user__ask` or `user__input` | ### Oracle Triggers (MUST spawn oracle when you see these) @@ -80,7 +79,7 @@ instructions: | 4. todo__add --task "Verify with build/test" 5. agent__spawn --agent explore --prompt "Find existing API endpoint patterns, route structures, and controller conventions" 6. agent__spawn --agent explore --prompt "Find existing data models and database query patterns" - 7. agent__collect --id # Collect exploration results + 7. agent__collect --id 8. agent__collect --id 9. todo__done --id 1 10. agent__spawn --agent coder --prompt "Create user profiles endpoint following existing patterns. [Include context from explore results]" @@ -124,9 +123,9 @@ instructions: | 4. **Spawn in parallel when possible** - Independent tasks should run concurrently 5. **Verify after collecting agent results** - Don't trust blindly 6. **Mark todos done immediately** - Don't batch completions - 7. **Ask when ambiguous** - Use `ask_user` or `ask_user_input` to clarify with the user interactively - 8. **Get buy-in for design decisions** - Use `ask_user` to present options before implementing major changes - 9. **Confirm destructive actions** - Use `ask_user_confirm` before large refactors or deletions + 7. **Ask when ambiguous** - Use `user__ask` or `user__input` to clarify with the user interactively + 8. **Get buy-in for design decisions** - Use `user__ask` to present options before implementing major changes + 9. **Confirm destructive actions** - Use `user__confirm` before large refactors or deletions ## When to Do It Yourself @@ -145,58 +144,18 @@ instructions: | ## User Interaction (CRITICAL - get buy-in before major decisions) - You have tools to prompt the user for input. Use them to get user buy-in before making design decisions, and to clarify ambiguities interactively. **Do NOT guess when you can ask.** + You have built-in tools to prompt the user for input. Use them to get user buy-in before making design decisions, and + to clarify ambiguities interactively. **Do NOT guess when you can ask.** ### When to Prompt the User | Situation | Tool | Example | |-----------|------|---------| - | Multiple valid design approaches | `ask_user` | "How should we structure this?" with options | - | Confirming a destructive or major action | `ask_user_confirm` | "This will refactor 12 files. Proceed?" | - | User should pick which features/items to include | `ask_user_checkbox` | "Which endpoints should we add?" | - | Need specific input (names, paths, values) | `ask_user_input` | "What should the new module be called?" | - | Ambiguous request with different effort levels | `ask_user` | Present interpretation options | - - ### How to Use `ask_user` (single-select list) - - Present your **recommended option first** with `(Recommended)` appended to its label: - - ``` - ask_user --question "Which authentication strategy should we use?" \ - --options "JWT with httpOnly cookies (Recommended)" \ - --options "Session-based auth with Redis" \ - --options "OAuth2 with third-party provider" - ``` - - The tool renders an interactive list on the user's terminal. They navigate with arrow keys and press Enter. The selected label is returned to you. - - ### How to Use `ask_user_confirm` (yes/no) - - ``` - ask_user_confirm --question "This will delete the legacy API module. Continue?" - ``` - - Returns "User confirmed: yes" or "User confirmed: no". **Respect the answer**; if the user says no, do NOT proceed with that action. - - ### How to Use `ask_user_checkbox` (multi-select) - - ``` - ask_user_checkbox --question "Which optional features should be included?" \ - --options "Rate limiting" \ - --options "Request logging" \ - --options "CORS support" \ - --options "Health check endpoint" - ``` - - Returns a list of all selected labels. The user selects items with Space and confirms with Enter. - - ### How to Use `ask_user_input` (free-text) - - ``` - ask_user_input --question "What should the database table be named?" - ``` - - Returns whatever text the user typed. + | Multiple valid design approaches | `user__ask` | "How should we structure this?" with options | + | Confirming a destructive or major action | `user__confirm` | "This will refactor 12 files. Proceed?" | + | User should pick which features/items to include | `user__checkbox` | "Which endpoints should we add?" | + | Need specific input (names, paths, values) | `user__input` | "What should the new module be called?" | + | Ambiguous request with different effort levels | `user__ask` | Present interpretation options | ### Design Review Pattern @@ -204,28 +163,24 @@ instructions: | 1. **Explore** the codebase to understand existing patterns 2. **Formulate** 2-3 design options based on findings - 3. **Present options** to the user via `ask_user` with your recommendation marked `(Recommended)` + 3. **Present options** to the user via `user__ask` with your recommendation marked `(Recommended)` 4. **Confirm** the chosen approach before delegating to `coder` 5. Proceed with implementation - Example flow: - ``` - 1. delegate_to_agent --agent explore --task "Find existing API patterns" - 2. ask_user --question "I found two patterns in the codebase. Which should we follow?" \ - --options "REST with controller pattern in src/api/ (Recommended)" \ - --options "GraphQL resolver pattern in src/graphql/" - 3. ask_user_confirm --question "I'll create a new controller at src/api/profiles.rs following the REST pattern. Proceed?" - 4. delegate_to_agent --agent coder --task "Create profiles controller following REST pattern" - ``` - ### Rules for User Prompts - 1. **Always include (Recommended)** on the option you think is best in `ask_user` + 1. **Always include (Recommended)** on the option you think is best in `user__ask` 2. **Respect user choices** - never override or ignore a selection 3. **Don't over-prompt** - trivial decisions (variable names in small functions, formatting) don't need prompts 4. **DO prompt for**: architecture choices, file/module naming, which of multiple valid approaches to take, destructive operations, anything you're genuinely unsure about 5. **Confirm before large changes** - if a task will touch 5+ files, confirm the plan first + ## Escalation Handling + + If you see `pending_escalations` in your tool results, a child agent needs user input and is blocked. + Reply promptly via `agent__reply_escalation` to unblock it. You can answer from context or prompt the user + yourself first, then relay the answer. + ## Available Tools {{__tools__}} diff --git a/assets/agents/sisyphus/tools.sh b/assets/agents/sisyphus/tools.sh index 955d9ab..3389f03 100755 --- a/assets/agents/sisyphus/tools.sh +++ b/assets/agents/sisyphus/tools.sh @@ -7,7 +7,7 @@ export AUTO_CONFIRM=true # @env LLM_OUTPUT=/dev/stdout # @env LLM_AGENT_VAR_PROJECT_DIR=. -# @describe Sisyphus orchestrator tools (project info, build, test, user interaction) +# @describe Sisyphus orchestrator tools (project info, build, test) _project_dir() { local dir="${LLM_AGENT_VAR_PROJECT_DIR:-.}" @@ -95,169 +95,3 @@ run_tests() { fi } -# @cmd Quick file search in the project -# @option --pattern! File name pattern to search for (e.g., "*.rs", "config*") -search_files() { - # shellcheck disable=SC2154 - local pattern="${argc_pattern}" - local project_dir - project_dir=$(_project_dir) - - info "Searching for: ${pattern}" >> "$LLM_OUTPUT" - echo "" >> "$LLM_OUTPUT" - - local results - results=$(search_files "${pattern}" "${project_dir}") - - if [[ -n "${results}" ]]; then - echo "${results}" >> "$LLM_OUTPUT" - else - warn "No files found matching: ${pattern}" >> "$LLM_OUTPUT" - fi -} - -# @cmd Search for content in files -# @option --pattern! Text pattern to search for -# @option --file-type File extension to search in (e.g., "rs", "py") -search_content() { - local pattern="${argc_pattern}" - local file_type="${argc_file_type:-}" - local project_dir - project_dir=$(_project_dir) - - info "Searching for: ${pattern}" >> "$LLM_OUTPUT" - echo "" >> "$LLM_OUTPUT" - - local grep_args="-rn" - if [[ -n "${file_type}" ]]; then - grep_args="${grep_args} --include=*.${file_type}" - fi - - local results - # shellcheck disable=SC2086 - results=$(grep ${grep_args} "${pattern}" "${project_dir}" 2>/dev/null | \ - grep -v '/target/' | grep -v '/node_modules/' | grep -v '/.git/' | \ - head -30) || true - - if [[ -n "${results}" ]]; then - echo "${results}" >> "$LLM_OUTPUT" - else - warn "No matches found for: ${pattern}" >> "$LLM_OUTPUT" - fi -} - -# @cmd Ask the user to select ONE option from a list. The first option should be your recommended choice; append '(Recommended)' to its label. Returns the selected option's label text. -# @option --question! The question to present to the user -# @option --options! The JSON array of options to present (first option = recommended, append '(Recommended)' to its label) -ask_user() { - # shellcheck disable=SC2154 - local question="${argc_question}" - - # shellcheck disable=SC2154 - local options_json="${argc_options}" - - local opts=() - - # Convert JSON array string -> Bash array - if ! mapfile -t opts < <(jq -r '.[]' <<<"$options_json"); then - error "Invalid JSON in argc_options" >> "$LLM_OUTPUT" - return 1 - fi - - local opts_count="${#opts[@]}" - - if [[ "$opts_count" -eq 0 ]]; then - error "No options provided for ask_user" >> "$LLM_OUTPUT" - return 1 - fi - - info "Asking user: ${question}" >> "$LLM_OUTPUT" - - local selected_index - selected_index=$(list "$question" "${opts[@]}" 2>/dev/tty) - - local selected_label="${opts[$selected_index]}" - - cat <<-EOF >> "$LLM_OUTPUT" - User selected: ${selected_label} - EOF -} - -# @cmd Ask the user a yes/no confirmation question. Returns 'yes' or 'no'. -# @option --question! The yes/no question to present to the user -ask_user_confirm() { - # shellcheck disable=SC2154 - local question="${argc_question}" - - info "Asking user: ${question}" >> "$LLM_OUTPUT" - - local result - result=$(confirm "${question}" 2>/dev/tty) - - if [[ "${result}" == "1" ]]; then - echo "User confirmed: yes" >> "$LLM_OUTPUT" - else - echo "User confirmed: no" >> "$LLM_OUTPUT" - fi -} - -# @cmd Ask the user to select MULTIPLE options from a list (checkbox). Returns the labels of all selected items. -# @option --question! The question to present to the user -# @option --options! The JSON array of options to present -ask_user_checkbox() { - # shellcheck disable=SC2154 - local question="${argc_question}" - # shellcheck disable=SC2154 - local options_json="${argc_options}" - - local opts=() - - # Convert JSON array string -> Bash array - if ! mapfile -t opts < <(jq -r '.[]' <<<"$options_json"); then - error "Invalid JSON in argc_options" >> "$LLM_OUTPUT" - return 1 - fi - local opts_count="${#opts[@]}" - - if [[ "${opts_count}" -eq 0 ]]; then - error "No options provided for ask_user_checkbox" >> "$LLM_OUTPUT" - return 1 - fi - - info "Asking user (select multiple): ${question}" >> "$LLM_OUTPUT" - - local checked_indices - checked_indices=$(checkbox "${question}" "${opts[@]}" 2>/dev/tty) - - local selected_labels=() - for idx in ${checked_indices}; do - if [[ -n "${idx}" ]] && [[ "${idx}" =~ ^[0-9]+$ ]]; then - selected_labels+=("${opts[$idx]}") - fi - done - - if [[ "${#selected_labels[@]}" -eq 0 ]]; then - echo "User selected: (none)" >> "$LLM_OUTPUT" - else - echo "User selected:" >> "$LLM_OUTPUT" - for label in "${selected_labels[@]}"; do - echo " - ${label}" >> "$LLM_OUTPUT" - done - fi -} - -# @cmd Ask the user for free-text input. Returns whatever the user typed. -# @option --question! The prompt/question to present to the user -ask_user_input() { - # shellcheck disable=SC2154 - local question="${argc_question}" - - info "Asking user: ${question}" >> "$LLM_OUTPUT" - - local user_text - user_text=$(input "${question}" 2>/dev/tty) - - cat <<-EOF >> "$LLM_OUTPUT" - User input: ${user_text} - EOF -}