ai-consultants 2.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/.claude/commands/ai-consultants:consult.md +94 -0
  2. package/.claude/commands/ai-consultants:debate.md +103 -0
  3. package/.claude/commands/ai-consultants:help.md +30 -0
  4. package/CLAUDE.md +839 -0
  5. package/LICENSE +21 -0
  6. package/README.md +758 -0
  7. package/SKILL.md +156 -0
  8. package/bin/ai-consultants +96 -0
  9. package/docs/COST_RATES.md +172 -0
  10. package/docs/JSON_SCHEMA.md +305 -0
  11. package/docs/SETUP.md +879 -0
  12. package/docs/SMART_ROUTING.md +219 -0
  13. package/docs/cost_rates.json +143 -0
  14. package/package.json +47 -0
  15. package/references/configuration.md +141 -0
  16. package/references/details.md +60 -0
  17. package/scripts/build_context.sh +562 -0
  18. package/scripts/classify_question.sh +148 -0
  19. package/scripts/config.sh +753 -0
  20. package/scripts/configure.sh +1093 -0
  21. package/scripts/consult_all.sh +934 -0
  22. package/scripts/debate_round.sh +421 -0
  23. package/scripts/doctor.sh +642 -0
  24. package/scripts/followup.sh +197 -0
  25. package/scripts/install.sh +319 -0
  26. package/scripts/lib/api.sh +640 -0
  27. package/scripts/lib/api_query.sh +228 -0
  28. package/scripts/lib/cache.sh +338 -0
  29. package/scripts/lib/chunking.sh +880 -0
  30. package/scripts/lib/code_optimizer.sh +671 -0
  31. package/scripts/lib/common.sh +1088 -0
  32. package/scripts/lib/costs.sh +674 -0
  33. package/scripts/lib/personas.sh +372 -0
  34. package/scripts/lib/progress.sh +251 -0
  35. package/scripts/lib/reflection.sh +447 -0
  36. package/scripts/lib/routing.sh +566 -0
  37. package/scripts/lib/schema.json +165 -0
  38. package/scripts/lib/session.sh +327 -0
  39. package/scripts/lib/symbol_map.sh +445 -0
  40. package/scripts/lib/voting.sh +495 -0
  41. package/scripts/peer_review.sh +460 -0
  42. package/scripts/preflight_check.sh +452 -0
  43. package/scripts/query_aider.sh +83 -0
  44. package/scripts/query_amp.sh +67 -0
  45. package/scripts/query_claude.sh +99 -0
  46. package/scripts/query_codex.sh +92 -0
  47. package/scripts/query_cursor.sh +72 -0
  48. package/scripts/query_deepseek.sh +17 -0
  49. package/scripts/query_gemini.sh +85 -0
  50. package/scripts/query_glm.sh +17 -0
  51. package/scripts/query_grok.sh +17 -0
  52. package/scripts/query_kilo.sh +140 -0
  53. package/scripts/query_kimi.sh +67 -0
  54. package/scripts/query_minimax.sh +17 -0
  55. package/scripts/query_mistral.sh +97 -0
  56. package/scripts/query_ollama.sh +328 -0
  57. package/scripts/query_qwen3.sh +93 -0
  58. package/scripts/setup_wizard.sh +367 -0
  59. package/scripts/skillport-install.sh +196 -0
  60. package/scripts/synthesize.sh +332 -0
  61. package/templates/consultation_report.md +323 -0
  62. package/templates/synthesis_prompt.md +120 -0
@@ -0,0 +1,452 @@
1
+ #!/bin/bash
2
+ # preflight_check.sh - Health check for AI Consultants v2.0
3
+ #
4
+ # Verifies that all consultants are available and functioning
5
+ # before starting a consultation.
6
+ #
7
+ # Usage: ./preflight_check.sh [--quick] [--json] [--suggest-config]
8
+ #
9
+ # Options:
10
+ # --quick Only check commands, no API tests
11
+ # --json Output in JSON format
12
+ # --suggest-config Output recommended ENABLE_* configuration
13
+
14
+ set -euo pipefail
15
+
16
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
17
+ source "$SCRIPT_DIR/lib/common.sh"
18
+
19
+ # --- Parameters ---
20
+ QUICK_MODE=false
21
+ JSON_OUTPUT=false
22
+ SUGGEST_CONFIG=false
23
+
24
+ while [[ $# -gt 0 ]]; do
25
+ case "$1" in
26
+ --quick)
27
+ QUICK_MODE=true
28
+ shift
29
+ ;;
30
+ --json)
31
+ JSON_OUTPUT=true
32
+ shift
33
+ ;;
34
+ --suggest-config)
35
+ SUGGEST_CONFIG=true
36
+ shift
37
+ ;;
38
+ *)
39
+ shift
40
+ ;;
41
+ esac
42
+ done
43
+
44
+ # --- State variables ---
45
+ # Using map_* functions from common.sh for bash 3.2 compatibility
46
+ # Maps: CLI_STATUS, API_STATUS, VERSIONS
47
+ ERRORS=0
48
+ WARNINGS=0
49
+
50
+ # =============================================================================
51
+ # CHECK FUNCTIONS
52
+ # =============================================================================
53
+
54
+ check_cli_installed() {
55
+ local name="$1"
56
+ local cmd="$2"
57
+ local install_hint="$3"
58
+
59
+ if command -v "$cmd" &> /dev/null; then
60
+ map_set "CLI_STATUS" "$name" "installed"
61
+ # Try to get version
62
+ local version
63
+ version=$("$cmd" --version 2>/dev/null | head -1 || echo "unknown")
64
+ map_set "VERSIONS" "$name" "$version"
65
+ return 0
66
+ else
67
+ map_set "CLI_STATUS" "$name" "missing"
68
+ map_set "VERSIONS" "$name" "N/A"
69
+ ((ERRORS++))
70
+ return 1
71
+ fi
72
+ }
73
+
74
+ check_api_connectivity() {
75
+ local name="$1"
76
+ local cmd="$2"
77
+ shift 2
78
+ local test_args=("$@")
79
+
80
+ if [[ "$(map_get "CLI_STATUS" "$name")" != "installed" ]]; then
81
+ map_set "API_STATUS" "$name" "skipped"
82
+ return 1
83
+ fi
84
+
85
+ # Quick test with timeout - properly quoted to prevent injection
86
+ if timeout 15 "$cmd" "${test_args[@]}" &>/dev/null; then
87
+ map_set "API_STATUS" "$name" "connected"
88
+ return 0
89
+ else
90
+ map_set "API_STATUS" "$name" "failed"
91
+ ((WARNINGS++))
92
+ return 1
93
+ fi
94
+ }
95
+
96
+ # =============================================================================
97
+ # SUGGEST CONFIGURATION
98
+ # =============================================================================
99
+
100
+ suggest_configuration() {
101
+ # Run quick checks first
102
+ check_cli_installed "Gemini" "$GEMINI_CMD" "npm install -g @google/gemini-cli" || true
103
+ check_cli_installed "Codex" "$CODEX_CMD" "npm install -g @openai/codex" || true
104
+ check_cli_installed "Mistral" "$MISTRAL_CMD" "pip install mistral-vibe" || true
105
+ check_cli_installed "Kilo" "$KILO_CMD" "npm install -g @kilocode/cli" || true
106
+ check_cli_installed "Cursor" "$CURSOR_CMD" "curl https://cursor.com/install -fsS | bash" || true
107
+ check_cli_installed "Aider" "$AIDER_CMD" "pip install aider-chat" || true
108
+
109
+ local gemini_enabled="false"
110
+ local codex_enabled="false"
111
+ local mistral_enabled="false"
112
+ local kilo_enabled="false"
113
+ local cursor_enabled="false"
114
+ local aider_enabled="false"
115
+ local available_count=0
116
+
117
+ [[ "$(map_get "CLI_STATUS" "Gemini")" == "installed" ]] && { gemini_enabled="true"; ((available_count++)); }
118
+ [[ "$(map_get "CLI_STATUS" "Codex")" == "installed" ]] && { codex_enabled="true"; ((available_count++)); }
119
+ [[ "$(map_get "CLI_STATUS" "Mistral")" == "installed" ]] && { mistral_enabled="true"; ((available_count++)); }
120
+ [[ "$(map_get "CLI_STATUS" "Kilo")" == "installed" ]] && { kilo_enabled="true"; ((available_count++)); }
121
+ [[ "$(map_get "CLI_STATUS" "Cursor")" == "installed" ]] && { cursor_enabled="true"; ((available_count++)); }
122
+ [[ "$(map_get "CLI_STATUS" "Aider")" == "installed" ]] && { aider_enabled="true"; ((available_count++)); }
123
+
124
+ echo "# Recommended configuration based on detected CLIs"
125
+ echo "# Generated by: ./preflight_check.sh --suggest-config"
126
+ echo "# Available consultants: $available_count/6"
127
+ echo ""
128
+ echo "ENABLE_GEMINI=$gemini_enabled"
129
+ echo "ENABLE_CODEX=$codex_enabled"
130
+ echo "ENABLE_MISTRAL=$mistral_enabled"
131
+ echo "ENABLE_KILO=$kilo_enabled"
132
+ echo "ENABLE_CURSOR=$cursor_enabled"
133
+ echo "ENABLE_AIDER=$aider_enabled"
134
+
135
+ if [[ $available_count -lt 2 ]]; then
136
+ echo ""
137
+ echo "# WARNING: Less than 2 consultants available."
138
+ echo "# AI Consultants requires at least 2 consultants."
139
+ echo "# Install more CLIs or run ./scripts/setup_wizard.sh"
140
+ fi
141
+ }
142
+
143
+ # =============================================================================
144
+ # MAIN CHECKS
145
+ # =============================================================================
146
+
147
+ run_preflight() {
148
+ if [[ "$JSON_OUTPUT" != "true" ]]; then
149
+ echo ""
150
+ echo "╔══════════════════════════════════════════════════════════════╗"
151
+ echo "║ AI Consultants v2.0 - Pre-flight Check ║"
152
+ echo "╚══════════════════════════════════════════════════════════════╝"
153
+ echo ""
154
+ fi
155
+
156
+ # --- Check CLI Installation ---
157
+ if [[ "$JSON_OUTPUT" != "true" ]]; then
158
+ echo "Checking CLI installations..."
159
+ echo ""
160
+ fi
161
+
162
+ check_cli_installed "Gemini" "$GEMINI_CMD" "npm install -g @google/gemini-cli"
163
+ check_cli_installed "Codex" "$CODEX_CMD" "npm install -g @openai/codex"
164
+ check_cli_installed "Mistral" "$MISTRAL_CMD" "pip install mistral-vibe"
165
+ check_cli_installed "Kilo" "$KILO_CMD" "npm install -g @kilocode/cli"
166
+ check_cli_installed "Cursor" "$CURSOR_CMD" "curl https://cursor.com/install -fsS | bash"
167
+ check_cli_installed "Aider" "$AIDER_CMD" "pip install aider-chat"
168
+
169
+ # Check API-based consultants (API key validation)
170
+ if [[ "$ENABLE_QWEN3" == "true" ]]; then
171
+ if [[ -z "${QWEN3_API_KEY:-}" ]]; then
172
+ map_set "CLI_STATUS" "Qwen3" "missing_key"
173
+ ((WARNINGS++))
174
+ else
175
+ map_set "CLI_STATUS" "Qwen3" "configured"
176
+ map_set "VERSIONS" "Qwen3" "API"
177
+ fi
178
+ fi
179
+
180
+ if [[ "$ENABLE_GLM" == "true" ]]; then
181
+ if [[ -z "${GLM_API_KEY:-}" ]]; then
182
+ map_set "CLI_STATUS" "GLM" "missing_key"
183
+ ((WARNINGS++))
184
+ else
185
+ map_set "CLI_STATUS" "GLM" "configured"
186
+ map_set "VERSIONS" "GLM" "API"
187
+ fi
188
+ fi
189
+
190
+ if [[ "$ENABLE_GROK" == "true" ]]; then
191
+ if [[ -z "${GROK_API_KEY:-}" ]]; then
192
+ map_set "CLI_STATUS" "Grok" "missing_key"
193
+ ((WARNINGS++))
194
+ else
195
+ map_set "CLI_STATUS" "Grok" "configured"
196
+ map_set "VERSIONS" "Grok" "API"
197
+ fi
198
+ fi
199
+
200
+ if [[ "$ENABLE_DEEPSEEK" == "true" ]]; then
201
+ if [[ -z "${DEEPSEEK_API_KEY:-}" ]]; then
202
+ map_set "CLI_STATUS" "DeepSeek" "missing_key"
203
+ ((WARNINGS++))
204
+ else
205
+ map_set "CLI_STATUS" "DeepSeek" "configured"
206
+ map_set "VERSIONS" "DeepSeek" "API"
207
+ fi
208
+ fi
209
+
210
+ # Check for jq (required for JSON processing)
211
+ if command -v jq &> /dev/null; then
212
+ map_set "CLI_STATUS" "jq" "installed"
213
+ map_set "VERSIONS" "jq" "$(jq --version 2>/dev/null || echo "unknown")"
214
+ else
215
+ map_set "CLI_STATUS" "jq" "missing"
216
+ map_set "VERSIONS" "jq" "N/A"
217
+ ((ERRORS++))
218
+ fi
219
+
220
+ # Check for bc (required for floating-point math in cost calculations)
221
+ if command -v bc &> /dev/null; then
222
+ map_set "CLI_STATUS" "bc" "installed"
223
+ map_set "VERSIONS" "bc" "$(bc --version 2>/dev/null | head -1 || echo "unknown")"
224
+ else
225
+ map_set "CLI_STATUS" "bc" "missing"
226
+ map_set "VERSIONS" "bc" "N/A"
227
+ ((ERRORS++))
228
+ fi
229
+
230
+ # Check for claude CLI (optional but recommended for synthesis)
231
+ if command -v claude &> /dev/null; then
232
+ map_set "CLI_STATUS" "claude" "installed"
233
+ map_set "VERSIONS" "claude" "$(claude --version 2>/dev/null | head -1 || echo "unknown")"
234
+ else
235
+ map_set "CLI_STATUS" "claude" "missing"
236
+ map_set "VERSIONS" "claude" "N/A"
237
+ ((WARNINGS++)) # Warning, not error - fallback available
238
+ fi
239
+
240
+ if [[ "$JSON_OUTPUT" != "true" ]]; then
241
+ # CLI-based consultants
242
+ for name in Gemini Codex Mistral Kilo Cursor jq bc claude; do
243
+ local status version
244
+ status=$(map_get "CLI_STATUS" "$name")
245
+ version=$(map_get "VERSIONS" "$name")
246
+ status="${status:-unknown}"
247
+ version="${version:-N/A}"
248
+ if [[ "$status" == "installed" ]]; then
249
+ echo " [OK] $name: $version"
250
+ elif [[ "$name" == "claude" ]]; then
251
+ echo " [WARN] $name: not installed (optional)"
252
+ else
253
+ echo " [FAIL] $name: NOT FOUND"
254
+ fi
255
+ done
256
+ # API-based consultants
257
+ for name in Qwen3 GLM Grok DeepSeek; do
258
+ local status
259
+ status=$(map_get "CLI_STATUS" "$name")
260
+ status="${status:-unknown}"
261
+ if [[ "$status" == "configured" ]]; then
262
+ echo " [OK] $name: API key configured"
263
+ elif [[ "$status" == "missing_key" ]]; then
264
+ echo " [WARN] $name: API key not set"
265
+ fi
266
+ done
267
+ echo ""
268
+ fi
269
+
270
+ # --- Check API Connectivity (unless quick mode) ---
271
+ if [[ "$QUICK_MODE" != "true" ]]; then
272
+ if [[ "$JSON_OUTPUT" != "true" ]]; then
273
+ echo "Testing API connectivity..."
274
+ echo ""
275
+ fi
276
+
277
+ # Gemini - test with version check
278
+ check_api_connectivity "Gemini" "$GEMINI_CMD" "--version" || true
279
+
280
+ # Codex - test with help
281
+ check_api_connectivity "Codex" "$CODEX_CMD" "--help" || true
282
+
283
+ # Mistral - test with help
284
+ check_api_connectivity "Mistral" "$MISTRAL_CMD" "--help" || true
285
+
286
+ # Kilo - test with version
287
+ check_api_connectivity "Kilo" "$KILO_CMD" "--version" || true
288
+
289
+ # Cursor - test with help
290
+ check_api_connectivity "Cursor" "$CURSOR_CMD" "--help" || true
291
+
292
+ # Aider - test with version
293
+ check_api_connectivity "Aider" "$AIDER_CMD" "--version" || true
294
+
295
+ if [[ "$JSON_OUTPUT" != "true" ]]; then
296
+ for name in Gemini Codex Mistral Kilo Cursor Aider; do
297
+ local status
298
+ status=$(map_get "API_STATUS" "$name")
299
+ status="${status:-skipped}"
300
+ case "$status" in
301
+ connected)
302
+ echo " [OK] $name: API reachable"
303
+ ;;
304
+ failed)
305
+ echo " [WARN] $name: API connection failed"
306
+ ;;
307
+ skipped)
308
+ echo " [SKIP] $name: skipped (CLI not installed)"
309
+ ;;
310
+ esac
311
+ done
312
+ echo ""
313
+ fi
314
+ fi
315
+
316
+ # --- Check enabled consultants ---
317
+ local enabled_count=0
318
+ # CLI-based consultants
319
+ [[ "$ENABLE_GEMINI" == "true" && "$(map_get "CLI_STATUS" "Gemini")" == "installed" ]] && ((enabled_count++))
320
+ [[ "$ENABLE_CODEX" == "true" && "$(map_get "CLI_STATUS" "Codex")" == "installed" ]] && ((enabled_count++))
321
+ [[ "$ENABLE_MISTRAL" == "true" && "$(map_get "CLI_STATUS" "Mistral")" == "installed" ]] && ((enabled_count++))
322
+ [[ "$ENABLE_KILO" == "true" && "$(map_get "CLI_STATUS" "Kilo")" == "installed" ]] && ((enabled_count++))
323
+ [[ "$ENABLE_CURSOR" == "true" && "$(map_get "CLI_STATUS" "Cursor")" == "installed" ]] && ((enabled_count++))
324
+ # API-based consultants
325
+ [[ "$ENABLE_QWEN3" == "true" && "$(map_get "CLI_STATUS" "Qwen3")" == "configured" ]] && ((enabled_count++))
326
+ [[ "$ENABLE_GLM" == "true" && "$(map_get "CLI_STATUS" "GLM")" == "configured" ]] && ((enabled_count++))
327
+ [[ "$ENABLE_GROK" == "true" && "$(map_get "CLI_STATUS" "Grok")" == "configured" ]] && ((enabled_count++))
328
+ [[ "$ENABLE_DEEPSEEK" == "true" && "$(map_get "CLI_STATUS" "DeepSeek")" == "configured" ]] && ((enabled_count++))
329
+
330
+ # --- Summary ---
331
+ if [[ "$JSON_OUTPUT" == "true" ]]; then
332
+ # Helper to get map value with default
333
+ get_or_default() {
334
+ local val
335
+ val=$(map_get "$1" "$2")
336
+ echo "${val:-$3}"
337
+ }
338
+
339
+ # JSON output using jq
340
+ jq -n \
341
+ --argjson errors "$ERRORS" \
342
+ --argjson warnings "$WARNINGS" \
343
+ --argjson enabled "$enabled_count" \
344
+ --arg gemini_cli "$(get_or_default CLI_STATUS Gemini unknown)" \
345
+ --arg codex_cli "$(get_or_default CLI_STATUS Codex unknown)" \
346
+ --arg mistral_cli "$(get_or_default CLI_STATUS Mistral unknown)" \
347
+ --arg kilo_cli "$(get_or_default CLI_STATUS Kilo unknown)" \
348
+ --arg cursor_cli "$(get_or_default CLI_STATUS Cursor unknown)" \
349
+ --arg jq_cli "$(get_or_default CLI_STATUS jq unknown)" \
350
+ --arg claude_cli "$(get_or_default CLI_STATUS claude unknown)" \
351
+ --arg gemini_api "$(get_or_default API_STATUS Gemini skipped)" \
352
+ --arg codex_api "$(get_or_default API_STATUS Codex skipped)" \
353
+ --arg mistral_api "$(get_or_default API_STATUS Mistral skipped)" \
354
+ --arg kilo_api "$(get_or_default API_STATUS Kilo skipped)" \
355
+ --arg cursor_api "$(get_or_default API_STATUS Cursor skipped)" \
356
+ --arg gemini_ver "$(get_or_default VERSIONS Gemini N/A)" \
357
+ --arg codex_ver "$(get_or_default VERSIONS Codex N/A)" \
358
+ --arg mistral_ver "$(get_or_default VERSIONS Mistral N/A)" \
359
+ --arg kilo_ver "$(get_or_default VERSIONS Kilo N/A)" \
360
+ --arg cursor_ver "$(get_or_default VERSIONS Cursor N/A)" \
361
+ '{
362
+ preflight: {
363
+ status: (if $errors > 0 then "failed" elif $warnings > 0 then "warning" else "ok" end),
364
+ errors: $errors,
365
+ warnings: $warnings,
366
+ enabled_consultants: $enabled
367
+ },
368
+ cli: {
369
+ Gemini: { status: $gemini_cli, version: $gemini_ver },
370
+ Codex: { status: $codex_cli, version: $codex_ver },
371
+ Mistral: { status: $mistral_cli, version: $mistral_ver },
372
+ Kilo: { status: $kilo_cli, version: $kilo_ver },
373
+ Cursor: { status: $cursor_cli, version: $cursor_ver },
374
+ jq: { status: $jq_cli },
375
+ claude: { status: $claude_cli }
376
+ },
377
+ api: {
378
+ Gemini: $gemini_api,
379
+ Codex: $codex_api,
380
+ Mistral: $mistral_api,
381
+ Kilo: $kilo_api,
382
+ Cursor: $cursor_api
383
+ }
384
+ }'
385
+ else
386
+ echo "╔══════════════════════════════════════════════════════════════╗"
387
+ echo "║ Summary ║"
388
+ echo "╚══════════════════════════════════════════════════════════════╝"
389
+ echo ""
390
+ echo " Enabled consultants: $enabled_count"
391
+ echo " Errors: $ERRORS"
392
+ echo " Warnings: $WARNINGS"
393
+ echo ""
394
+
395
+ if [[ $ERRORS -gt 0 ]]; then
396
+ echo " [FAIL] Pre-flight FAILED - fix errors before proceeding"
397
+ echo ""
398
+ echo " Installation hints:"
399
+ [[ "$(map_get "CLI_STATUS" "Gemini")" == "missing" ]] && echo " npm install -g @google/gemini-cli"
400
+ [[ "$(map_get "CLI_STATUS" "Codex")" == "missing" ]] && echo " npm install -g @openai/codex"
401
+ [[ "$(map_get "CLI_STATUS" "Mistral")" == "missing" ]] && echo " pip install mistral-vibe"
402
+ [[ "$(map_get "CLI_STATUS" "Kilo")" == "missing" ]] && echo " npm install -g @kilocode/cli"
403
+ [[ "$(map_get "CLI_STATUS" "Cursor")" == "missing" ]] && echo " curl https://cursor.com/install -fsS | bash"
404
+ [[ "$(map_get "CLI_STATUS" "jq")" == "missing" ]] && echo " brew install jq # or apt install jq"
405
+ [[ "$(map_get "CLI_STATUS" "bc")" == "missing" ]] && echo " brew install bc # or apt install bc"
406
+ echo ""
407
+ exit 1
408
+ elif [[ $WARNINGS -gt 0 ]]; then
409
+ echo " [WARN] Pre-flight PASSED with warnings"
410
+ echo ""
411
+ exit 0
412
+ else
413
+ echo " [OK] Pre-flight PASSED - all systems go!"
414
+ echo ""
415
+ exit 0
416
+ fi
417
+ fi
418
+ }
419
+
420
+ # =============================================================================
421
+ # RUN
422
+ # =============================================================================
423
+
424
+ # --- Run Unit Tests (optional) ---
425
+ run_unit_tests() {
426
+ if [[ -f "$SCRIPT_DIR/test_functions.sh" ]]; then
427
+ if [[ "$JSON_OUTPUT" != "true" ]]; then
428
+ echo "Running unit tests..."
429
+ echo ""
430
+ fi
431
+
432
+ if "$SCRIPT_DIR/test_functions.sh"; then
433
+ if [[ "$JSON_OUTPUT" != "true" ]]; then
434
+ echo " [OK] Unit tests: PASSED"
435
+ echo ""
436
+ fi
437
+ else
438
+ if [[ "$JSON_OUTPUT" != "true" ]]; then
439
+ echo " [WARN] Unit tests: FAILED"
440
+ echo ""
441
+ fi
442
+ ((WARNINGS++))
443
+ fi
444
+ fi
445
+ }
446
+
447
+ if [[ "$SUGGEST_CONFIG" == "true" ]]; then
448
+ suggest_configuration
449
+ else
450
+ run_preflight
451
+ run_unit_tests
452
+ fi
@@ -0,0 +1,83 @@
1
+ #!/bin/bash
2
+ # query_aider.sh - Query Aider CLI
3
+ #
4
+ # Usage: ./query_aider.sh "question" [context_file] [output_file]
5
+ #
6
+ # Environment variables:
7
+ # AIDER_MODEL - Model to use (default: uses aider's default)
8
+ # AIDER_TIMEOUT - Timeout in seconds (default: 180)
9
+ # ENABLE_PERSONA - Enable "The Pair Programmer" persona (default: true)
10
+
11
+ set -euo pipefail
12
+
13
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
14
+ source "$SCRIPT_DIR/lib/common.sh"
15
+ source "$SCRIPT_DIR/lib/personas.sh"
16
+
17
+ # --- Parameters ---
18
+ QUERY="${1:-}"
19
+ CONTEXT_FILE="${2:-}"
20
+ OUTPUT_FILE="${3:-/tmp/aider_response.json}"
21
+
22
+ # --- Configuration ---
23
+ ENABLE_PERSONA="${ENABLE_PERSONA:-true}"
24
+ CONSULTANT_NAME="Aider"
25
+
26
+ # --- Check prerequisites ---
27
+ check_command "$AIDER_CMD" "Aider CLI" "pip install aider-chat" || exit 1
28
+
29
+ # --- Build query ---
30
+ FULL_QUERY=$(build_full_query "$QUERY" "$CONTEXT_FILE")
31
+ validate_query "$FULL_QUERY" "Aider" || exit 1
32
+
33
+ # --- Add persona if enabled ---
34
+ if [[ "$ENABLE_PERSONA" == "true" ]]; then
35
+ FULL_QUERY=$(build_query_with_persona "$CONSULTANT_NAME" "$FULL_QUERY")
36
+ fi
37
+
38
+ # --- Timestamp for metadata ---
39
+ START_TIME=$(get_timestamp_ms)
40
+
41
+ # --- Execution ---
42
+ TEMP_OUTPUT=$(mktemp)
43
+
44
+ # Aider flags:
45
+ # --no-git: Don't use git
46
+ # --message: Send message and exit
47
+ # --yes: Answer yes to all prompts
48
+ # --no-check-update: Don't check for updates
49
+ # --no-suggest-shell-commands: Don't suggest shell commands
50
+ run_query \
51
+ "Aider" \
52
+ "$TEMP_OUTPUT" \
53
+ "$AIDER_TIMEOUT_SECONDS" \
54
+ "$AIDER_CMD" --no-git --no-check-update --no-suggest-shell-commands --yes --message "$FULL_QUERY"
55
+
56
+ exit_code=$?
57
+
58
+ # --- Calculate latency ---
59
+ END_TIME=$(get_timestamp_ms)
60
+ LATENCY_MS=$((END_TIME - START_TIME))
61
+
62
+ # --- Configuration for response building ---
63
+ MODEL_USED="${AIDER_MODEL:-gpt-5.3-codex}"
64
+ PERSONA_NAME=$(get_persona_name "$CONSULTANT_NAME")
65
+
66
+ # --- Post-processing: wrap in full schema using shared helpers ---
67
+ if [[ $exit_code -eq 0 && -f "$TEMP_OUTPUT" && -s "$TEMP_OUTPUT" ]]; then
68
+ RAW_RESPONSE=$(cat "$TEMP_OUTPUT")
69
+ rm -f "$TEMP_OUTPUT"
70
+
71
+ # Try to parse as structured JSON
72
+ if echo "$RAW_RESPONSE" | jq -e '.response.summary' > /dev/null 2>&1; then
73
+ build_structured_response "$CONSULTANT_NAME" "$MODEL_USED" "$PERSONA_NAME" "$RAW_RESPONSE" "$LATENCY_MS" > "$OUTPUT_FILE"
74
+ else
75
+ build_fallback_response "$CONSULTANT_NAME" "$MODEL_USED" "$PERSONA_NAME" "$RAW_RESPONSE" "$LATENCY_MS" > "$OUTPUT_FILE"
76
+ fi
77
+ else
78
+ rm -f "$TEMP_OUTPUT"
79
+ build_error_response "$CONSULTANT_NAME" "$MODEL_USED" "$PERSONA_NAME" "Query failed with exit code $exit_code" "$LATENCY_MS" > "$OUTPUT_FILE"
80
+ fi
81
+
82
+ cat "$OUTPUT_FILE"
83
+ exit $exit_code
@@ -0,0 +1,67 @@
1
+ #!/bin/bash
2
+ # query_amp.sh - Query Amp CLI (v2.8)
3
+ #
4
+ # Usage: ./query_amp.sh "question" [context_file] [output_file]
5
+ #
6
+ # Environment variables:
7
+ # AMP_MODEL - Model identifier (default: amp)
8
+ # AMP_TIMEOUT - Timeout in seconds (default: 180)
9
+ # AMP_API_KEY - API key for authentication (required)
10
+ # ENABLE_PERSONA - Enable "The Systems Thinker" persona (default: true)
11
+
12
+ set -euo pipefail
13
+
14
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
+ source "$SCRIPT_DIR/lib/common.sh"
16
+ source "$SCRIPT_DIR/lib/personas.sh"
17
+
18
+ # --- Parameters ---
19
+ QUERY="${1:-}"
20
+ CONTEXT_FILE="${2:-}"
21
+ OUTPUT_FILE="${3:-/tmp/amp_response.json}"
22
+
23
+ # --- Configuration ---
24
+ ENABLE_PERSONA="${ENABLE_PERSONA:-true}"
25
+ CONSULTANT_NAME="Amp"
26
+
27
+ # --- Build query ---
28
+ FULL_QUERY=$(build_full_query "$QUERY" "$CONTEXT_FILE")
29
+ validate_query "$FULL_QUERY" "Amp" || exit 1
30
+
31
+ # --- Add persona if enabled ---
32
+ if [[ "$ENABLE_PERSONA" == "true" ]]; then
33
+ FULL_QUERY=$(build_query_with_persona "$CONSULTANT_NAME" "$FULL_QUERY")
34
+ fi
35
+
36
+ # --- Timestamp for metadata ---
37
+ START_TIME=$(get_timestamp_ms)
38
+
39
+ # --- Execution ---
40
+ TEMP_OUTPUT=$(mktemp)
41
+
42
+ # Check CLI prerequisite
43
+ check_command "$AMP_CMD" "Amp CLI" "curl -fsSL https://ampcode.com/install.sh | bash" || exit 1
44
+
45
+ # Amp CLI uses -x (execute mode) for non-interactive usage
46
+ echo "$FULL_QUERY" | run_query \
47
+ "Amp" \
48
+ "$TEMP_OUTPUT" \
49
+ "$AMP_TIMEOUT_SECONDS" \
50
+ "$AMP_CMD" -x
51
+
52
+ exit_code=$?
53
+
54
+ # --- Calculate latency ---
55
+ END_TIME=$(get_timestamp_ms)
56
+ LATENCY_MS=$((END_TIME - START_TIME))
57
+
58
+ # --- Configuration for response building ---
59
+ MODEL_USED="${AMP_MODEL:-amp}"
60
+ PERSONA_NAME=$(get_persona_name "$CONSULTANT_NAME")
61
+
62
+ # --- Post-processing: use shared helper ---
63
+ process_consultant_response "$CONSULTANT_NAME" "$MODEL_USED" "$PERSONA_NAME" \
64
+ "$TEMP_OUTPUT" "$OUTPUT_FILE" "$exit_code" "$LATENCY_MS"
65
+
66
+ cat "$OUTPUT_FILE"
67
+ exit $exit_code