test-prompt.sh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. #!/bin/bash
  2. #
  3. # test-prompt.sh - Test a specific prompt variant for an agent
  4. #
  5. # Usage:
  6. # ./scripts/prompts/test-prompt.sh --agent=openagent --variant=default
  7. # ./scripts/prompts/test-prompt.sh --agent=openagent --variant=default --model=anthropic/claude-sonnet-4-5
  8. # ./scripts/prompts/test-prompt.sh --agent=openagent --variant=sonnet-4 --model=opencode/grok-code-fast
  9. #
  10. # What it does:
  11. # 1. Backs up current agent prompt
  12. # 2. Copies the specified prompt variant to the agent location
  13. # 3. Runs the eval tests with specified model (defaults to Sonnet 4.5)
  14. # 4. Restores the original prompt (keeps default in place)
  15. # 5. Outputs results summary
  16. #
  17. set -e
  18. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  19. ROOT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
  20. # Colors
  21. RED='\033[0;31m'
  22. GREEN='\033[0;32m'
  23. YELLOW='\033[1;33m'
  24. BLUE='\033[0;34m'
  25. NC='\033[0m' # No Color
  26. # Default values
  27. AGENT_NAME=""
  28. PROMPT_VARIANT=""
  29. MODEL="" # Will be set from metadata or user input
  30. # Paths
  31. PROMPTS_DIR="$ROOT_DIR/.opencode/prompts"
  32. AGENT_DIR="$ROOT_DIR/.opencode/agent"
  33. EVALS_DIR="$ROOT_DIR/evals/framework"
  34. RESULTS_FILE="$ROOT_DIR/evals/results/latest.json"
  35. # Function to extract metadata from prompt file
  36. extract_metadata() {
  37. local file="$1"
  38. local key="$2"
  39. # Extract YAML frontmatter between --- markers
  40. # Look for key in the metadata section
  41. awk -v key="$key" '
  42. /^---$/ { in_yaml = !in_yaml; next }
  43. in_yaml && $0 ~ "^" key ":" {
  44. sub("^" key ": *", "")
  45. gsub(/"/, "")
  46. print
  47. exit
  48. }
  49. ' "$file"
  50. }
  51. # Function to extract recommended models array from metadata
  52. extract_recommended_models() {
  53. local file="$1"
  54. # Extract recommended_models array from YAML
  55. awk '
  56. /^---$/ { in_yaml = !in_yaml; next }
  57. in_yaml && /^recommended_models:/ { in_models = 1; next }
  58. in_yaml && in_models && /^ - / {
  59. # Remove leading spaces, dash, and quotes
  60. gsub(/^ - /, "")
  61. gsub(/"/, "")
  62. # Remove comments
  63. sub(/ *#.*$/, "")
  64. # Trim whitespace
  65. gsub(/^ +| +$/, "")
  66. print
  67. }
  68. in_yaml && in_models && /^[a-z_]+:/ { exit }
  69. ' "$file"
  70. }
  71. usage() {
  72. echo "Usage: $0 --agent=<name> --variant=<name> [--model=<model>]"
  73. echo ""
  74. echo "Required:"
  75. echo " --agent=NAME Agent name (e.g., openagent, opencoder)"
  76. echo " --variant=NAME Prompt variant by model family (e.g., default, gpt, gemini, grok, llama)"
  77. echo ""
  78. echo "Optional:"
  79. echo " --model=MODEL Model to test with (uses prompt metadata if not specified)"
  80. echo " --help, -h Show this help"
  81. echo ""
  82. echo "Examples:"
  83. echo " # Test with default (Claude) - uses metadata recommendation"
  84. echo " $0 --agent=openagent --variant=default"
  85. echo ""
  86. echo " # Test GPT prompt - uses metadata recommendation (gpt-4o)"
  87. echo " $0 --agent=openagent --variant=gpt"
  88. echo ""
  89. echo " # Test Gemini prompt with specific model"
  90. echo " $0 --agent=openagent --variant=gemini --model=google/gemini-2.0-flash-exp"
  91. echo ""
  92. echo " # Test Grok prompt - uses metadata recommendation (free tier)"
  93. echo " $0 --agent=openagent --variant=grok"
  94. echo ""
  95. echo "Available model families:"
  96. echo " default # Claude Sonnet 4.5 (stable)"
  97. echo " gpt # OpenAI GPT-4o, GPT-4o-mini, o1"
  98. echo " gemini # Google Gemini 2.0 Flash, Pro"
  99. echo " grok # xAI Grok (free tier available)"
  100. echo " llama # Meta Llama 3.1/3.2 (local or hosted)"
  101. echo ""
  102. echo "Note: Each prompt contains metadata with recommended models."
  103. echo " If --model is not specified, the primary recommendation is used."
  104. echo ""
  105. echo "Available prompts for an agent:"
  106. echo " ls $PROMPTS_DIR/<agent-name>/"
  107. exit 1
  108. }
  109. # Parse arguments
  110. for arg in "$@"; do
  111. case $arg in
  112. --agent=*)
  113. AGENT_NAME="${arg#*=}"
  114. shift
  115. ;;
  116. --variant=*)
  117. PROMPT_VARIANT="${arg#*=}"
  118. shift
  119. ;;
  120. --model=*)
  121. MODEL="${arg#*=}"
  122. shift
  123. ;;
  124. --help|-h)
  125. usage
  126. ;;
  127. *)
  128. echo -e "${RED}Unknown argument: $arg${NC}"
  129. echo ""
  130. usage
  131. ;;
  132. esac
  133. done
  134. # Validate required arguments
  135. if [[ -z "$AGENT_NAME" ]] || [[ -z "$PROMPT_VARIANT" ]]; then
  136. echo -e "${RED}Error: Missing required arguments${NC}"
  137. echo ""
  138. usage
  139. fi
  140. PROMPT_FILE="$PROMPTS_DIR/$AGENT_NAME/$PROMPT_VARIANT.md"
  141. AGENT_FILE="$AGENT_DIR/$AGENT_NAME.md"
  142. BACKUP_FILE="$AGENT_DIR/.$AGENT_NAME.md.backup"
  143. VARIANT_RESULTS_DIR="$PROMPTS_DIR/$AGENT_NAME/results"
  144. VARIANT_RESULTS_FILE="$VARIANT_RESULTS_DIR/$PROMPT_VARIANT-results.json"
  145. # Check prompt exists
  146. if [[ ! -f "$PROMPT_FILE" ]]; then
  147. echo -e "${RED}Error: Prompt not found: $PROMPT_FILE${NC}"
  148. echo ""
  149. echo "Available prompts for $AGENT_NAME:"
  150. ls -1 "$PROMPTS_DIR/$AGENT_NAME/"*.md 2>/dev/null | xargs -I {} basename {} .md || echo " (none found)"
  151. exit 1
  152. fi
  153. # Read metadata from prompt file
  154. MODEL_FAMILY=$(extract_metadata "$PROMPT_FILE" "model_family")
  155. RECOMMENDED_MODELS=$(extract_recommended_models "$PROMPT_FILE")
  156. # If no model specified, suggest from metadata
  157. if [[ -z "$MODEL" ]]; then
  158. if [[ -n "$RECOMMENDED_MODELS" ]]; then
  159. echo -e "${YELLOW}No model specified. Reading recommendations from prompt metadata...${NC}"
  160. echo ""
  161. echo -e "${BLUE}Recommended models for '$PROMPT_VARIANT' (${MODEL_FAMILY} family):${NC}"
  162. # Display recommended models with numbers
  163. i=1
  164. while IFS= read -r model; do
  165. echo " $i. $model"
  166. if [[ $i -eq 1 ]]; then
  167. PRIMARY_MODEL="$model"
  168. fi
  169. ((i++))
  170. done <<< "$RECOMMENDED_MODELS"
  171. echo ""
  172. echo -e "${YELLOW}Using primary recommendation: ${GREEN}$PRIMARY_MODEL${NC}"
  173. echo ""
  174. echo "To use a different model, run with: --model=<model-id>"
  175. echo ""
  176. MODEL="$PRIMARY_MODEL"
  177. else
  178. # Fallback to default if no metadata
  179. echo -e "${YELLOW}No metadata found. Using default model: anthropic/claude-sonnet-4-5${NC}"
  180. MODEL="anthropic/claude-sonnet-4-5"
  181. fi
  182. fi
  183. echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
  184. echo -e "${BLUE}║ Testing Prompt: $AGENT_NAME / $PROMPT_VARIANT${NC}"
  185. echo -e "${BLUE}║ Model: $MODEL${NC}"
  186. echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
  187. echo ""
  188. # Step 1: Backup current agent prompt
  189. echo -e "${YELLOW}[1/5] Backing up current agent prompt...${NC}"
  190. if [[ -f "$AGENT_FILE" ]]; then
  191. cp "$AGENT_FILE" "$BACKUP_FILE"
  192. echo " Backed up to $BACKUP_FILE"
  193. else
  194. echo " No existing agent file to backup"
  195. fi
  196. # Step 2: Copy prompt variant to agent location
  197. echo -e "${YELLOW}[2/5] Copying prompt variant to agent location...${NC}"
  198. cp "$PROMPT_FILE" "$AGENT_FILE"
  199. echo " Copied $PROMPT_FILE"
  200. echo " To $AGENT_FILE"
  201. # Step 3: Run tests
  202. echo -e "${YELLOW}[3/5] Running core eval tests...${NC}"
  203. echo ""
  204. echo -e "${BLUE}Model: ${GREEN}$MODEL${NC}"
  205. echo -e "${BLUE}Running 7 core tests (estimated 5-8 minutes):${NC}"
  206. echo " 1. Approval Gate"
  207. echo " 2. Context Loading (Simple)"
  208. echo " 3. Context Loading (Multi-Turn)"
  209. echo " 4. Stop on Failure"
  210. echo " 5. Simple Task (No Delegation)"
  211. echo " 6. Subagent Delegation"
  212. echo " 7. Tool Usage"
  213. echo ""
  214. echo -e "${BLUE}Test output:${NC}"
  215. echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
  216. echo ""
  217. cd "$EVALS_DIR"
  218. # Run tests with real-time output
  219. set +e # Don't exit on test failure
  220. npm run eval:sdk:core -- --agent="$AGENT_NAME" --model="$MODEL"
  221. TEST_EXIT_CODE=$?
  222. set -e
  223. echo ""
  224. echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
  225. # Step 4: Restore default prompt
  226. echo ""
  227. echo -e "${YELLOW}[4/5] Restoring default prompt...${NC}"
  228. DEFAULT_PROMPT="$PROMPTS_DIR/$AGENT_NAME/default.md"
  229. if [[ -f "$DEFAULT_PROMPT" ]]; then
  230. cp "$DEFAULT_PROMPT" "$AGENT_FILE"
  231. echo " Restored default.md to agent location"
  232. else
  233. # Restore backup if no default
  234. if [[ -f "$BACKUP_FILE" ]]; then
  235. cp "$BACKUP_FILE" "$AGENT_FILE"
  236. echo " Restored from backup"
  237. fi
  238. fi
  239. # Clean up backup
  240. rm -f "$BACKUP_FILE"
  241. # Step 5: Save and show results summary
  242. echo ""
  243. echo -e "${YELLOW}[5/5] Saving Results${NC}"
  244. # Create results directory if it doesn't exist
  245. mkdir -p "$VARIANT_RESULTS_DIR"
  246. # Save the test output for reference
  247. if [[ -f "/tmp/test-output-$AGENT_NAME.txt" ]]; then
  248. cp "/tmp/test-output-$AGENT_NAME.txt" "$VARIANT_RESULTS_DIR/$PROMPT_VARIANT-output.log"
  249. echo " Saved test output to: $VARIANT_RESULTS_DIR/$PROMPT_VARIANT-output.log"
  250. fi
  251. if [[ -f "$RESULTS_FILE" ]]; then
  252. # Extract summary from results JSON
  253. if command -v jq &> /dev/null; then
  254. PASS_COUNT=$(jq -r '.summary.passed // 0' "$RESULTS_FILE")
  255. TOTAL_COUNT=$(jq -r '.summary.total // 0' "$RESULTS_FILE")
  256. FAIL_COUNT=$(jq -r '.summary.failed // 0' "$RESULTS_FILE")
  257. else
  258. # Fallback if jq not available
  259. PASS_COUNT=$(grep -o '"passed":[0-9]*' "$RESULTS_FILE" | head -1 | grep -o '[0-9]*')
  260. TOTAL_COUNT=$(grep -o '"total":[0-9]*' "$RESULTS_FILE" | head -1 | grep -o '[0-9]*')
  261. FAIL_COUNT=$((TOTAL_COUNT - PASS_COUNT))
  262. fi
  263. # Calculate pass rate
  264. if [ $TOTAL_COUNT -gt 0 ]; then
  265. PASS_RATE=$(echo "scale=1; ($PASS_COUNT * 100) / $TOTAL_COUNT" | bc)
  266. else
  267. PASS_RATE="0.0"
  268. fi
  269. # Create variant results JSON
  270. cat > "$VARIANT_RESULTS_FILE" <<EOF
  271. {
  272. "variant": "$PROMPT_VARIANT",
  273. "agent": "$AGENT_NAME",
  274. "model": "$MODEL",
  275. "timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
  276. "passed": $PASS_COUNT,
  277. "failed": $FAIL_COUNT,
  278. "total": $TOTAL_COUNT,
  279. "passRate": "${PASS_RATE}%",
  280. "fullResults": "$RESULTS_FILE"
  281. }
  282. EOF
  283. echo " Saved results to: $VARIANT_RESULTS_FILE"
  284. echo ""
  285. echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
  286. echo ""
  287. echo -e " Agent: ${GREEN}$AGENT_NAME${NC}"
  288. echo -e " Prompt: ${GREEN}$PROMPT_VARIANT${NC}"
  289. echo -e " Model: ${GREEN}$MODEL${NC}"
  290. echo -e " Results: ${GREEN}$PASS_COUNT/$TOTAL_COUNT tests passed${NC} (${PASS_RATE}%)"
  291. echo ""
  292. echo " Variant results: $VARIANT_RESULTS_FILE"
  293. echo " Full results: $RESULTS_FILE"
  294. else
  295. echo -e " ${RED}No results file found${NC}"
  296. echo " Tests may not have run successfully"
  297. fi
  298. echo ""
  299. echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
  300. echo ""
  301. echo -e "${GREEN}Done!${NC} Default prompt restored to agent location."
  302. echo ""
  303. echo "To use this prompt permanently:"
  304. echo " ./scripts/prompts/use-prompt.sh --agent=$AGENT_NAME --variant=$PROMPT_VARIANT"