#!/usr/bin/env bash # Purpose: State machine for /prompt command orchestration # Inputs: Structured XML via stdin OR command-line args for initial state # Outputs: Next instruction for /prompt command # Architecture: State machine that guides /prompt through: # - Without --plan: optimizer → executor → done # - With --plan: optimizer → Plan agent → executor → done set -euo pipefail # Source common functions SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" . "$SCRIPT_DIR/../../scripts/common.sh" # Detect current state from input detect_state() { local input="$1" if echo "$input" | grep -q ""; then echo "post_template_selector" elif echo "$input" | grep -q ""; then echo "post_optimizer" elif echo "$input" | grep -q ""; then echo "post_plan" elif echo "$input" | grep -q ""; then echo "final" else # Initial state (command-line args or initial XML) echo "initial" fi } # Parse flags from initial task description # Sets global variables: RETURN_ONLY, PLAN, TEMPLATE, TEMPLATE_FLAG_SEEN, TASK_DESCRIPTION parse_initial_flags() { local raw_input="$1" # Set global variables for use by handler functions RETURN_ONLY=false PLAN=false TEMPLATE="" TEMPLATE_FLAG_SEEN=false # Parse all flags from the beginning of the input while true; do case "$raw_input" in --template=*) if [ "$TEMPLATE_FLAG_SEEN" = true ]; then echo "Error: Multiple template flags specified." >&2 exit 1 fi TEMPLATE="${raw_input#--template=}" TEMPLATE="${TEMPLATE%% *}" raw_input="${raw_input#--template=$TEMPLATE}" raw_input="${raw_input# }" TEMPLATE_FLAG_SEEN=true ;; --code\ *|--code) if [ "$TEMPLATE_FLAG_SEEN" = true ]; then echo "Error: Multiple template flags specified." >&2 echo "Already set: $TEMPLATE" >&2 echo "Cannot use multiple template flags in one command." >&2 exit 1 fi TEMPLATE="code-refactoring" TEMPLATE_FLAG_SEEN=true raw_input="${raw_input#--code}" raw_input="${raw_input# }" ;; --refactor\ *|--refactor) if [ "$TEMPLATE_FLAG_SEEN" = true ]; then echo "Error: Multiple template flags specified." >&2 exit 1 fi TEMPLATE="code-refactoring" TEMPLATE_FLAG_SEEN=true raw_input="${raw_input#--refactor}" raw_input="${raw_input# }" ;; --review\ *|--review) if [ "$TEMPLATE_FLAG_SEEN" = true ]; then echo "Error: Multiple template flags specified." >&2 exit 1 fi TEMPLATE="code-review" TEMPLATE_FLAG_SEEN=true raw_input="${raw_input#--review}" raw_input="${raw_input# }" ;; --test\ *|--test) if [ "$TEMPLATE_FLAG_SEEN" = true ]; then echo "Error: Multiple template flags specified." >&2 exit 1 fi TEMPLATE="test-generation" TEMPLATE_FLAG_SEEN=true raw_input="${raw_input#--test}" raw_input="${raw_input# }" ;; --docs\ *|--docs) if [ "$TEMPLATE_FLAG_SEEN" = true ]; then echo "Error: Multiple template flags specified." >&2 exit 1 fi TEMPLATE="documentation-generator" TEMPLATE_FLAG_SEEN=true raw_input="${raw_input#--docs}" raw_input="${raw_input# }" ;; --documentation\ *|--documentation) if [ "$TEMPLATE_FLAG_SEEN" = true ]; then echo "Error: Multiple template flags specified." >&2 exit 1 fi TEMPLATE="documentation-generator" TEMPLATE_FLAG_SEEN=true raw_input="${raw_input#--documentation}" raw_input="${raw_input# }" ;; --extract\ *|--extract) if [ "$TEMPLATE_FLAG_SEEN" = true ]; then echo "Error: Multiple template flags specified." >&2 exit 1 fi TEMPLATE="data-extraction" TEMPLATE_FLAG_SEEN=true raw_input="${raw_input#--extract}" raw_input="${raw_input# }" ;; --compare\ *|--compare) if [ "$TEMPLATE_FLAG_SEEN" = true ]; then echo "Error: Multiple template flags specified." >&2 exit 1 fi TEMPLATE="code-comparison" TEMPLATE_FLAG_SEEN=true raw_input="${raw_input#--compare}" raw_input="${raw_input# }" ;; --comparison\ *|--comparison) if [ "$TEMPLATE_FLAG_SEEN" = true ]; then echo "Error: Multiple template flags specified." >&2 exit 1 fi TEMPLATE="code-comparison" TEMPLATE_FLAG_SEEN=true raw_input="${raw_input#--comparison}" raw_input="${raw_input# }" ;; --custom\ *|--custom) if [ "$TEMPLATE_FLAG_SEEN" = true ]; then echo "Error: Multiple template flags specified." >&2 exit 1 fi TEMPLATE="custom" TEMPLATE_FLAG_SEEN=true raw_input="${raw_input#--custom}" raw_input="${raw_input# }" ;; --return-only\ *|--return-only) RETURN_ONLY=true raw_input="${raw_input#--return-only}" raw_input="${raw_input# }" ;; --plan\ *|--plan) PLAN=true raw_input="${raw_input#--plan}" raw_input="${raw_input# }" ;; *) # No more flags, break out of loop break ;; esac done # Validate template name if provided if [ -n "$TEMPLATE" ]; then case "$TEMPLATE" in code-refactoring|code-review|test-generation|documentation-generator|data-extraction|code-comparison|custom) # Valid template ;; *) echo "Error: Invalid template name: $TEMPLATE" >&2 exit 1 ;; esac fi # Normalize whitespace and set global TASK_DESCRIPTION raw_input=$(echo "$raw_input" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/[[:space:]][[:space:]]*/ /g') TASK_DESCRIPTION="$raw_input" } # Handle initial state - spawn template-selector or prompt-optimizer handle_initial_state() { parse_initial_flags "$1" # Sanitize for shell safety, then escape for CDATA safety local sanitized_task=$(escape_cdata "$(sanitize_input "$TASK_DESCRIPTION")") # If no template specified, spawn template-selector first if [ -z "$TEMPLATE" ]; then cat < initial spawn_template_selector meta-prompt:template-selector Select template for task $sanitized_task Follow your instructions to classify the task and return the result in XML format.]]> ...(full XML output)... $sanitized_task $PLAN $RETURN_ONLY']]> EOF return fi # Template already specified, proceed to optimizer # Determine execution mode local execution_mode="direct" if [ "$PLAN" = true ]; then execution_mode="plan" fi # Build template XML local template_xml="" # Check if return-only mode if [ "$RETURN_ONLY" = true ]; then cat < initial spawn_optimizer_return_only meta-prompt:prompt-optimizer Create optimized prompt $sanitized_task$template_xml $execution_mode Follow your instructions to process the template and return the result in XML format.]]> present_optimized_prompt EOF else cat < initial spawn_optimizer meta-prompt:prompt-optimizer Create optimized prompt $sanitized_task$template_xml $execution_mode Follow your instructions to process the template and return the result in XML format.]]> ...(full XML output)...']]> EOF fi } # Handle post-template-selector state - spawn prompt-optimizer with selected template handle_post_template_selector_state() { local selector_output="$1" # Extract values from XML using sed (BSD-compatible) local selected_template=$(echo "$selector_output" | sed -n 's/.*\(.*\)<\/selected_template>.*/\1/p') local original_task=$(echo "$selector_output" | sed -n 's/.*\(.*\)<\/original_task>.*/\1/p') local plan_flag=$(echo "$selector_output" | sed -n 's/.*\(.*\)<\/plan_flag>.*/\1/p') local return_only_flag=$(echo "$selector_output" | sed -n 's/.*\(.*\)<\/return_only_flag>.*/\1/p') # Sanitize for shell safety, then escape for CDATA safety local sanitized_task=$(escape_cdata "$(sanitize_input "$original_task")") # Determine execution mode local execution_mode="direct" if [ "$plan_flag" = "true" ]; then execution_mode="plan" fi # Build template XML local template_xml="" # Check if return-only mode if [ "$return_only_flag" = "true" ]; then cat < post_template_selector spawn_optimizer_return_only meta-prompt:prompt-optimizer Create optimized prompt $sanitized_task$template_xml $execution_mode Follow your instructions to process the template and return the result in XML format.]]> present_optimized_prompt EOF else cat < post_template_selector spawn_optimizer meta-prompt:prompt-optimizer Create optimized prompt $sanitized_task$template_xml $execution_mode Follow your instructions to process the template and return the result in XML format.]]> ...(full XML output)...']]> EOF fi } # Handle post-optimizer state - spawn Plan or template-executor handle_post_optimizer_state() { local optimizer_output="$1" # Extract values from XML using sed (BSD-compatible) local skill=$(echo "$optimizer_output" | sed -n 's/.*\(.*\)<\/skill>.*/\1/p') local execution_mode=$(echo "$optimizer_output" | sed -n 's/.*\(.*\)<\/execution_mode>.*/\1/p') local optimized_prompt=$(echo "$optimizer_output" | sed -n 's/.*\(.*\)<\/optimized_prompt>.*/\1/p') # Sanitize for shell safety, then escape for CDATA safety local sanitized_skill=$(escape_cdata "$(sanitize_input "$skill")") local sanitized_prompt=$(escape_cdata "$optimized_prompt") if [ "$execution_mode" = "plan" ]; then cat < post_optimizer spawn_plan_agent Plan Create execution plan $sanitized_skill $sanitized_prompt ']]> EOF else cat < post_optimizer spawn_template_executor meta-prompt:template-executor Execute task $sanitized_skill $sanitized_prompt Follow your instructions to load the skill (if not 'none') and execute the task.]]> present_results EOF fi } # Handle post-plan state - spawn template-executor with the plan handle_post_plan_state() { local plan_output="$1" # Extract values from XML using sed (BSD-compatible) local skill=$(echo "$plan_output" | sed -n 's/.*\(.*\)<\/skill>.*/\1/p') # Extract optimized_prompt (multiline content) local optimized_prompt=$(echo "$plan_output" | sed -n '//,/<\/optimized_prompt>/p' | sed '1d;$d') # Sanitize for shell safety, then escape for CDATA safety local sanitized_skill=$(escape_cdata "$(sanitize_input "$skill")") local sanitized_prompt=$(escape_cdata "$optimized_prompt") cat < post_plan spawn_template_executor meta-prompt:template-executor Execute task $sanitized_skill $sanitized_prompt Follow your instructions to load the skill (if not 'none') and execute the task.]]> present_results EOF } # Handle final state - just present results handle_final_state() { cat < final done present_results EOF } # Main state machine logic main() { # Check if input is provided as command-line arg if [ $# -gt 0 ]; then # Use command-line args INPUT="$1" # Detect state from input STATE=$(detect_state "$INPUT") else # No input provided echo "Error: No input provided. Usage: $0 ''" >&2 echo " Or: $0 ''" >&2 exit 1 fi # Execute state handler case "$STATE" in initial) handle_initial_state "$INPUT" ;; post_template_selector) handle_post_template_selector_state "$INPUT" ;; post_optimizer) handle_post_optimizer_state "$INPUT" ;; post_plan) handle_post_plan_state "$INPUT" ;; final) handle_final_state ;; *) echo "Error: Unknown state: $STATE" >&2 exit 1 ;; esac } # Run main function main "$@"