ai-consultants 4.0.2 → 4.0.4
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.
- package/.env.example +8 -11
- package/CLAUDE.md +18 -2
- package/README.md +13 -118
- package/SKILL.md +7 -3
- package/docs/COST_RATES.md +7 -4
- package/docs/JSON_SCHEMA.md +1 -1
- package/docs/SETUP.md +10 -25
- package/docs/SMART_ROUTING.md +8 -50
- package/docs/cost_rates.json +10 -5
- package/package.json +2 -1
- package/references/configuration.md +1 -1
- package/scripts/config.sh +9 -22
- package/scripts/configure.sh +8 -5
- package/scripts/consult_all.sh +3 -3
- package/scripts/doctor.sh +4 -4
- package/scripts/install.sh +2 -2
- package/scripts/lib/api.sh +0 -55
- package/scripts/lib/cache.sh +0 -24
- package/scripts/lib/code_optimizer.sh +0 -53
- package/scripts/lib/common.sh +1 -57
- package/scripts/lib/costs.sh +0 -17
- package/scripts/lib/personas.sh +0 -18
- package/scripts/lib/reliability.sh +0 -23
- package/scripts/lib/routing.sh +18 -119
- package/scripts/lib/session.sh +0 -81
- package/scripts/query_glm.sh +1 -1
- package/docs/releases/v2.10.1.md +0 -84
- package/docs/releases/v2.10.2.md +0 -40
- package/docs/releases/v2.10.3.md +0 -63
- package/docs/releases/v2.10.4.md +0 -63
- package/docs/releases/v2.10.5.md +0 -57
- package/docs/releases/v2.10.6.md +0 -59
- package/docs/releases/v2.10.7.md +0 -53
- package/docs/releases/v2.10.8.md +0 -58
- package/docs/releases/v2.10.9.md +0 -123
- package/docs/releases/v2.11.0.md +0 -163
- package/docs/releases/v2.12.0.md +0 -182
- package/docs/releases/v2.13.0.md +0 -179
- package/docs/releases/v2.13.1.md +0 -133
- package/docs/releases/v2.14.0.md +0 -124
- package/docs/releases/v2.14.1.md +0 -70
- package/docs/releases/v2.14.2.md +0 -77
- package/docs/releases/v2.15.0.md +0 -72
- package/docs/releases/v2.15.1.md +0 -80
- package/docs/releases/v2.16.0.md +0 -71
- package/docs/releases/v2.17.0.md +0 -62
- package/docs/releases/v2.17.1.md +0 -46
- package/docs/releases/v2.17.2.md +0 -51
- package/docs/releases/v2.18.0.md +0 -63
- package/docs/releases/v2.19.0.md +0 -66
- package/docs/releases/v2.19.1.md +0 -44
- package/docs/releases/v2.19.2.md +0 -54
- package/docs/releases/v2.20.0.md +0 -65
- package/docs/releases/v2.21.0.md +0 -65
- package/docs/releases/v2.21.1.md +0 -84
- package/docs/releases/v2.22.0.md +0 -82
- package/docs/releases/v2.23.0.md +0 -75
- package/docs/releases/v2.24.0.md +0 -88
- package/docs/releases/v2.25.0.md +0 -101
- package/docs/releases/v2.25.1.md +0 -77
- package/docs/releases/v2.25.2.md +0 -53
- package/docs/releases/v3.0.0.md +0 -71
- package/docs/releases/v3.1.0.md +0 -95
- package/docs/releases/v3.1.1.md +0 -54
- package/docs/releases/v3.2.0.md +0 -96
- package/docs/releases/v3.3.0.md +0 -80
- package/docs/releases/v3.4.0.md +0 -102
- package/docs/releases/v3.5.0.md +0 -129
- package/docs/releases/v4.0.0.md +0 -107
- package/docs/releases/v4.0.1.md +0 -57
- package/docs/releases/v4.0.2.md +0 -98
package/scripts/config.sh
CHANGED
|
@@ -186,7 +186,7 @@ QWEN3_FORMAT="${QWEN3_FORMAT:-qwen}"
|
|
|
186
186
|
# GLM CONFIGURATION - The Code Specialist (API-based)
|
|
187
187
|
# =============================================================================
|
|
188
188
|
|
|
189
|
-
GLM_MODEL="${GLM_MODEL:-glm-5.3}"
|
|
189
|
+
GLM_MODEL="${GLM_MODEL:-glm-5.3-flash}"
|
|
190
190
|
GLM_TIMEOUT_SECONDS="${GLM_TIMEOUT:-180}"
|
|
191
191
|
GLM_API_MAX_TOKENS="${GLM_API_MAX_TOKENS:-16384}"
|
|
192
192
|
GLM_API_URL="${GLM_API_URL:-https://api.z.ai/api/coding/paas/v4/chat/completions}"
|
|
@@ -304,12 +304,6 @@ CLAUDE_CMD="${CLAUDE_CMD:-claude}"
|
|
|
304
304
|
# All available consultants (ordered by typical usage)
|
|
305
305
|
ALL_CONSULTANTS=("Gemini" "Codex" "Mistral" "Kimi" "Claude" "Qwen3" "GLM" "Grok" "DeepSeek" "MiniMax")
|
|
306
306
|
|
|
307
|
-
# CLI-based consultants (use CLI tools, some support CLI/API switching)
|
|
308
|
-
CLI_CONSULTANTS=("Gemini" "Codex" "Mistral" "Kimi" "Claude" "Qwen3" "Grok" "MiniMax")
|
|
309
|
-
|
|
310
|
-
# API-only consultants (use HTTP API directly, no CLI available)
|
|
311
|
-
API_CONSULTANTS=("GLM" "DeepSeek")
|
|
312
|
-
|
|
313
307
|
# =============================================================================
|
|
314
308
|
# ENABLED CONSULTANTS
|
|
315
309
|
# =============================================================================
|
|
@@ -435,17 +429,11 @@ BUDGET_ACTION="${BUDGET_ACTION:-warn}"
|
|
|
435
429
|
# (persistent across reboots; sessions enable follow-up queries).
|
|
436
430
|
SESSION_DIR="${SESSION_DIR:-${_AI_CONSULTANTS_XDG_STATE}/sessions}"
|
|
437
431
|
|
|
438
|
-
#
|
|
432
|
+
# Deprecated no-op; retained through v4.x for configuration compatibility.
|
|
439
433
|
SESSION_CLEANUP_DAYS="${SESSION_CLEANUP_DAYS:-7}"
|
|
440
434
|
|
|
441
|
-
#
|
|
442
|
-
# INTERACTIVE MODE (v2.0)
|
|
443
|
-
# =============================================================================
|
|
444
|
-
|
|
445
|
-
# Enable interactive progress bars
|
|
435
|
+
# Deprecated no-ops; retained through v4.x for configuration compatibility.
|
|
446
436
|
ENABLE_PROGRESS_BARS="${ENABLE_PROGRESS_BARS:-true}"
|
|
447
|
-
|
|
448
|
-
# Enable early termination (Ctrl+C to stop with partial responses)
|
|
449
437
|
ENABLE_EARLY_TERMINATION="${ENABLE_EARLY_TERMINATION:-true}"
|
|
450
438
|
|
|
451
439
|
# =============================================================================
|
|
@@ -485,7 +473,7 @@ ENABLE_SEMANTIC_CHUNKING="${ENABLE_SEMANTIC_CHUNKING:-true}"
|
|
|
485
473
|
# Maximum tokens per chunk (for chunking mode)
|
|
486
474
|
CHUNK_MAX_TOKENS="${CHUNK_MAX_TOKENS:-500}"
|
|
487
475
|
|
|
488
|
-
#
|
|
476
|
+
# Deprecated no-op; retained through v4.x for configuration compatibility.
|
|
489
477
|
USE_COMPACT_PROMPTS="${USE_COMPACT_PROMPTS:-true}"
|
|
490
478
|
|
|
491
479
|
# Extract only essential fields for synthesis (instead of full JSON)
|
|
@@ -525,8 +513,7 @@ USE_ECONOMIC_MODELS_FOR_SIMPLE="${USE_ECONOMIC_MODELS_FOR_SIMPLE:-true}"
|
|
|
525
513
|
COMPLEXITY_THRESHOLD_SIMPLE="${COMPLEXITY_THRESHOLD_SIMPLE:-3}"
|
|
526
514
|
COMPLEXITY_THRESHOLD_MEDIUM="${COMPLEXITY_THRESHOLD_MEDIUM:-6}"
|
|
527
515
|
|
|
528
|
-
#
|
|
529
|
-
# Send only relevant files to each consultant
|
|
516
|
+
# Deprecated no-ops; retained through v4.x for configuration compatibility.
|
|
530
517
|
ENABLE_SELECTIVE_CONTEXT="${ENABLE_SELECTIVE_CONTEXT:-false}"
|
|
531
518
|
MAX_FILES_PER_CONSULTANT="${MAX_FILES_PER_CONSULTANT:-5}"
|
|
532
519
|
|
|
@@ -623,7 +610,7 @@ get_model_for_tier() {
|
|
|
623
610
|
codex) echo "gpt-5.6-sol" ;;
|
|
624
611
|
mistral) [[ "$transport" == "api" ]] && echo "mistral-large-3" || echo "mistral-medium-3.5" ;;
|
|
625
612
|
deepseek) echo "deepseek-v4-pro" ;;
|
|
626
|
-
glm) echo "glm-5.3" ;;
|
|
613
|
+
glm) echo "glm-5.3-flash" ;;
|
|
627
614
|
grok) echo "grok-4.6" ;;
|
|
628
615
|
qwen3) echo "qwen3.8-max" ;;
|
|
629
616
|
kimi) echo "kimi-code/k3-256k" ;;
|
|
@@ -638,7 +625,7 @@ get_model_for_tier() {
|
|
|
638
625
|
codex) echo "gpt-5.6-sol" ;;
|
|
639
626
|
mistral) [[ "$transport" == "api" ]] && echo "mistral-large-3" || echo "mistral-medium-3.5" ;;
|
|
640
627
|
deepseek) echo "deepseek-v4-pro" ;;
|
|
641
|
-
glm) echo "glm-5.3" ;;
|
|
628
|
+
glm) echo "glm-5.3-flash" ;;
|
|
642
629
|
grok) echo "grok-4.6" ;;
|
|
643
630
|
qwen3) echo "qwen3.7-max" ;;
|
|
644
631
|
kimi) echo "kimi-code/k3" ;;
|
|
@@ -653,7 +640,7 @@ get_model_for_tier() {
|
|
|
653
640
|
codex) echo "gpt-5.6-terra" ;;
|
|
654
641
|
mistral) [[ "$transport" == "api" ]] && echo "mistral-large-3" || echo "mistral-medium-3.5" ;;
|
|
655
642
|
deepseek) echo "deepseek-v4-flash" ;;
|
|
656
|
-
glm) echo "glm-5.3" ;; # Same as premium (no mid-tier GLM)
|
|
643
|
+
glm) echo "glm-5.3-flash" ;; # Same as premium (no mid-tier GLM)
|
|
657
644
|
grok) echo "grok-4.5" ;;
|
|
658
645
|
qwen3) echo "qwen3.6-35b-a3b" ;; # Open-weight MoE (35B total, 3B active)
|
|
659
646
|
kimi) echo "kimi-code/k3" ;;
|
|
@@ -1011,4 +998,4 @@ EOF
|
|
|
1011
998
|
# VERSION
|
|
1012
999
|
# =============================================================================
|
|
1013
1000
|
|
|
1014
|
-
AI_CONSULTANTS_VERSION="4.0.
|
|
1001
|
+
AI_CONSULTANTS_VERSION="4.0.4"
|
package/scripts/configure.sh
CHANGED
|
@@ -307,11 +307,14 @@ if [[ "$(read_value "$WORK_FILE" GEMINI_MODEL 2>/dev/null || true)" == "Gemini 3
|
|
|
307
307
|
echo "Migrated managed Gemini CLI default: Gemini 3.1 Pro (High) -> Gemini 3.7 Flash (High)" >&2
|
|
308
308
|
fi
|
|
309
309
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
310
|
+
case "$(read_value "$WORK_FILE" GLM_MODEL 2>/dev/null || true)" in
|
|
311
|
+
glm-5.2|glm-5.3)
|
|
312
|
+
if ! has_value_marker "$WORK_FILE" GLM_MODEL "$PIN_MARKER"; then
|
|
313
|
+
set_value GLM_MODEL "glm-5.3-flash $DEFAULT_MARKER"
|
|
314
|
+
echo "Migrated managed GLM default to glm-5.3-flash" >&2
|
|
315
|
+
fi
|
|
316
|
+
;;
|
|
317
|
+
esac
|
|
315
318
|
|
|
316
319
|
if [[ "$(read_value "$WORK_FILE" GROK_MODEL 2>/dev/null || true)" == "grok-4.5" ]] \
|
|
317
320
|
&& ! has_value_marker "$WORK_FILE" GROK_MODEL "$PIN_MARKER"; then
|
package/scripts/consult_all.sh
CHANGED
|
@@ -489,12 +489,12 @@ if [[ ${#SELECTED_CONSULTANTS[@]} -eq 0 ]]; then
|
|
|
489
489
|
exit 1
|
|
490
490
|
fi
|
|
491
491
|
|
|
492
|
-
# Minimum 2 consultants required for
|
|
492
|
+
# Minimum 2 consultants required for a coverage panel
|
|
493
493
|
if [[ ${#SELECTED_CONSULTANTS[@]} -lt 2 ]]; then
|
|
494
|
-
log_error "At least 2 consultants required for
|
|
494
|
+
log_error "At least 2 consultants are required for a coverage panel."
|
|
495
495
|
log_error "Currently enabled: ${#SELECTED_CONSULTANTS[@]} (${SELECTED_CONSULTANTS[*]})"
|
|
496
496
|
echo "" >&2
|
|
497
|
-
log_info "Run
|
|
497
|
+
log_info "Run \"$SCRIPT_DIR/../bin/ai-consultants\" configure to configure additional consultants"
|
|
498
498
|
log_info "Or manually enable more:"
|
|
499
499
|
log_info " ENABLE_GEMINI=true ENABLE_CODEX=true ./scripts/consult_all.sh \"query\""
|
|
500
500
|
exit 1
|
package/scripts/doctor.sh
CHANGED
|
@@ -413,11 +413,11 @@ check_configuration() {
|
|
|
413
413
|
check_pass
|
|
414
414
|
elif [[ $enabled_count -eq 1 ]]; then
|
|
415
415
|
_print " ✗ Enabled consultants: $enabled_count (need at least 2)"
|
|
416
|
-
add_issue "config" "Only 1 consultant enabled, need at least 2" "Run:
|
|
416
|
+
add_issue "config" "Only 1 consultant enabled, need at least 2" "Run: \"$SCRIPT_DIR/../bin/ai-consultants\" configure"
|
|
417
417
|
check_fail
|
|
418
418
|
else
|
|
419
419
|
_print " ✗ Enabled consultants: 0 (need at least 2)"
|
|
420
|
-
add_issue "config" "No consultants enabled" "Run:
|
|
420
|
+
add_issue "config" "No consultants enabled" "Run: \"$SCRIPT_DIR/../bin/ai-consultants\" configure"
|
|
421
421
|
check_fail
|
|
422
422
|
fi
|
|
423
423
|
|
|
@@ -825,8 +825,8 @@ suggest_configuration() {
|
|
|
825
825
|
if (( available_count < 2 )); then
|
|
826
826
|
echo ""
|
|
827
827
|
echo "# WARNING: Less than 2 consultants available."
|
|
828
|
-
echo "# AI Consultants requires at least 2
|
|
829
|
-
echo "# Install more CLIs or run
|
|
828
|
+
echo "# AI Consultants requires at least 2 for a coverage panel."
|
|
829
|
+
echo "# Install more CLIs or run \"$SCRIPT_DIR/../bin/ai-consultants\" configure"
|
|
830
830
|
fi
|
|
831
831
|
}
|
|
832
832
|
|
package/scripts/install.sh
CHANGED
|
@@ -348,8 +348,8 @@ echo "━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
348
348
|
echo ""
|
|
349
349
|
log_info "Option B: Configure via Bash"
|
|
350
350
|
echo ""
|
|
351
|
-
echo " 1.
|
|
352
|
-
echo " $INSTALL_DIR/
|
|
351
|
+
echo " 1. Configure available consultants:"
|
|
352
|
+
echo " $INSTALL_DIR/bin/ai-consultants configure"
|
|
353
353
|
echo ""
|
|
354
354
|
echo " 2. Run a consultation:"
|
|
355
355
|
echo " $INSTALL_DIR/scripts/consult_all.sh \"Your question\""
|
package/scripts/lib/api.sh
CHANGED
|
@@ -38,46 +38,6 @@ sanitize_error_message() {
|
|
|
38
38
|
-e 's/([a-zA-Z0-9_-]{32,})/[POSSIBLE_KEY]/g'
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
# =============================================================================
|
|
42
|
-
# API KEY VALIDATION
|
|
43
|
-
# =============================================================================
|
|
44
|
-
|
|
45
|
-
# Check if an API key environment variable is set
|
|
46
|
-
# Usage: check_api_key "QWEN3_API_KEY" "Qwen3"
|
|
47
|
-
check_api_key() {
|
|
48
|
-
local key_var_name="$1"
|
|
49
|
-
local consultant_name="$2"
|
|
50
|
-
|
|
51
|
-
# Get the value of the environment variable by name
|
|
52
|
-
local key_value="${!key_var_name:-}"
|
|
53
|
-
|
|
54
|
-
if [[ -z "$key_value" ]]; then
|
|
55
|
-
log_error "[$consultant_name] API key not set: $key_var_name"
|
|
56
|
-
log_info "Set the $key_var_name environment variable to use $consultant_name"
|
|
57
|
-
return 1
|
|
58
|
-
fi
|
|
59
|
-
|
|
60
|
-
# Basic validation: key should be non-empty and not contain obvious placeholders
|
|
61
|
-
if [[ "$key_value" == *"your_"* ]] || [[ "$key_value" == *"YOUR_"* ]] || [[ "$key_value" == "xxx"* ]]; then
|
|
62
|
-
log_error "[$consultant_name] API key appears to be a placeholder: $key_var_name"
|
|
63
|
-
return 1
|
|
64
|
-
fi
|
|
65
|
-
|
|
66
|
-
# Validate key format (minimum length, no whitespace)
|
|
67
|
-
if [[ ${#key_value} -lt 10 ]]; then
|
|
68
|
-
log_error "[$consultant_name] API key too short: $key_var_name"
|
|
69
|
-
return 1
|
|
70
|
-
fi
|
|
71
|
-
|
|
72
|
-
if [[ "$key_value" =~ [[:space:]] ]]; then
|
|
73
|
-
log_error "[$consultant_name] API key contains whitespace: $key_var_name"
|
|
74
|
-
return 1
|
|
75
|
-
fi
|
|
76
|
-
|
|
77
|
-
log_debug "[$consultant_name] API key validated"
|
|
78
|
-
return 0
|
|
79
|
-
}
|
|
80
|
-
|
|
81
41
|
# =============================================================================
|
|
82
42
|
# HTTP ERROR HANDLING
|
|
83
43
|
# =============================================================================
|
|
@@ -724,18 +684,3 @@ check_rate_limit() {
|
|
|
724
684
|
|
|
725
685
|
return 0
|
|
726
686
|
}
|
|
727
|
-
|
|
728
|
-
# Clear rate limit state for a consultant (useful for testing)
|
|
729
|
-
# Usage: clear_rate_limit <consultant_name>
|
|
730
|
-
clear_rate_limit() {
|
|
731
|
-
local consultant_name="$1"
|
|
732
|
-
local safe_name=$(echo "$consultant_name" | tr '[:upper:]' '[:lower:]' | tr -cs '[:alnum:]' '_')
|
|
733
|
-
local state_file="${RATE_LIMIT_DIR}/${safe_name}_ratelimit"
|
|
734
|
-
|
|
735
|
-
rm -f "$state_file" 2>/dev/null || true
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
# Clear all rate limit state
|
|
739
|
-
clear_all_rate_limits() {
|
|
740
|
-
rm -rf "$RATE_LIMIT_DIR" 2>/dev/null || true
|
|
741
|
-
}
|
package/scripts/lib/cache.sh
CHANGED
|
@@ -228,30 +228,6 @@ store_cache() {
|
|
|
228
228
|
mv "$temp_file" "$cache_file"
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
# Invalidate cache for a specific query
|
|
232
|
-
# Usage: invalidate_cache <query> <category> [consultant] [context_file]
|
|
233
|
-
invalidate_cache() {
|
|
234
|
-
local query="$1"
|
|
235
|
-
local category="${2:-GENERAL}"
|
|
236
|
-
local consultant="${3:-}"
|
|
237
|
-
local context_file="${4:-}"
|
|
238
|
-
|
|
239
|
-
init_cache
|
|
240
|
-
|
|
241
|
-
local fingerprint
|
|
242
|
-
fingerprint=$(generate_fingerprint "$query" "$category" "$context_file")
|
|
243
|
-
|
|
244
|
-
if [[ -n "$consultant" ]]; then
|
|
245
|
-
# Invalidate specific consultant cache
|
|
246
|
-
local cache_file
|
|
247
|
-
cache_file=$(_get_cache_path "$fingerprint" "$consultant")
|
|
248
|
-
rm -f "$cache_file" 2>/dev/null || true
|
|
249
|
-
else
|
|
250
|
-
# Invalidate all caches for this fingerprint
|
|
251
|
-
rm -f "${CACHE_DIR}"/*_"${fingerprint}".json 2>/dev/null || true
|
|
252
|
-
fi
|
|
253
|
-
}
|
|
254
|
-
|
|
255
231
|
# Clear all expired cache entries
|
|
256
232
|
# Usage: cleanup_cache
|
|
257
233
|
cleanup_cache() {
|
|
@@ -616,56 +616,3 @@ optimize_code_files() {
|
|
|
616
616
|
log_success "Optimized $processed of $total_files files"
|
|
617
617
|
}
|
|
618
618
|
|
|
619
|
-
# =============================================================================
|
|
620
|
-
# TOKEN ESTIMATION
|
|
621
|
-
# =============================================================================
|
|
622
|
-
|
|
623
|
-
# Estimate token savings from optimization
|
|
624
|
-
# Usage: estimate_token_savings "/path/to/file.py"
|
|
625
|
-
# Returns: JSON with original_tokens, optimized_tokens, savings_percent
|
|
626
|
-
estimate_token_savings() {
|
|
627
|
-
local file_path="$1"
|
|
628
|
-
|
|
629
|
-
if [ ! -f "$file_path" ]; then
|
|
630
|
-
log_error "File not found: $file_path"
|
|
631
|
-
return 1
|
|
632
|
-
fi
|
|
633
|
-
|
|
634
|
-
# Get original size
|
|
635
|
-
local original_chars
|
|
636
|
-
original_chars=$(wc -c < "$file_path" | tr -d ' ')
|
|
637
|
-
local original_tokens=$((original_chars / 4))
|
|
638
|
-
|
|
639
|
-
# Get optimized size
|
|
640
|
-
local optimized_content
|
|
641
|
-
optimized_content=$(optimize_code_file "$file_path")
|
|
642
|
-
local optimized_chars
|
|
643
|
-
optimized_chars=$(echo -n "$optimized_content" | wc -c | tr -d ' ')
|
|
644
|
-
local optimized_tokens=$((optimized_chars / 4))
|
|
645
|
-
|
|
646
|
-
# Calculate savings
|
|
647
|
-
local savings_percent=0
|
|
648
|
-
if [ "$original_tokens" -gt 0 ]; then
|
|
649
|
-
savings_percent=$(( (original_tokens - optimized_tokens) * 100 / original_tokens ))
|
|
650
|
-
fi
|
|
651
|
-
|
|
652
|
-
# Output JSON
|
|
653
|
-
cat <<EOF
|
|
654
|
-
{
|
|
655
|
-
"file": "$file_path",
|
|
656
|
-
"original_tokens": $original_tokens,
|
|
657
|
-
"optimized_tokens": $optimized_tokens,
|
|
658
|
-
"savings_tokens": $((original_tokens - optimized_tokens)),
|
|
659
|
-
"savings_percent": $savings_percent
|
|
660
|
-
}
|
|
661
|
-
EOF
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
# Check if a file should be optimized based on extension
|
|
665
|
-
# Usage: is_optimizable_file "/path/to/file.py"
|
|
666
|
-
is_optimizable_file() {
|
|
667
|
-
local lang
|
|
668
|
-
lang=$(detect_language "$1")
|
|
669
|
-
[ "$lang" != "unknown" ]
|
|
670
|
-
}
|
|
671
|
-
|
package/scripts/lib/common.sh
CHANGED
|
@@ -310,7 +310,7 @@ KNOWN_API_AGENTS="GLM DEEPSEEK"
|
|
|
310
310
|
# therefore a latent phantom-consultant bug, not a cosmetic omission -- it had
|
|
311
311
|
# drifted 18 flags out of date before the pin below existed.
|
|
312
312
|
# KEEP IN SYNC with the top-level ENABLE_* declarations in config.sh;
|
|
313
|
-
#
|
|
313
|
+
# test_common.sh::test_known_feature_flags_in_sync fails the build otherwise.
|
|
314
314
|
KNOWN_FEATURE_FLAGS="PERSONA SYNTHESIS CLASSIFICATION SMART_ROUTING \
|
|
315
315
|
COST_TRACKING PROGRESS_BARS EARLY_TERMINATION PREFLIGHT \
|
|
316
316
|
AST_EXTRACTION BUDGET_LIMIT \
|
|
@@ -835,29 +835,6 @@ estimate_tokens() {
|
|
|
835
835
|
echo $((chars / 4))
|
|
836
836
|
}
|
|
837
837
|
|
|
838
|
-
# Estimate tokens from a file
|
|
839
|
-
# Usage: estimate_tokens_file "/path/to/file"
|
|
840
|
-
estimate_tokens_file() {
|
|
841
|
-
local file_path="$1"
|
|
842
|
-
if [[ -f "$file_path" ]]; then
|
|
843
|
-
local chars
|
|
844
|
-
chars=$(wc -c < "$file_path" | tr -d ' ')
|
|
845
|
-
echo $((chars / 4))
|
|
846
|
-
else
|
|
847
|
-
echo 0
|
|
848
|
-
fi
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
# Log token estimate with label
|
|
852
|
-
# Usage: log_token_estimate "Prompt" "$prompt_text"
|
|
853
|
-
log_token_estimate() {
|
|
854
|
-
local label="$1"
|
|
855
|
-
local text="$2"
|
|
856
|
-
local tokens
|
|
857
|
-
tokens=$(estimate_tokens "$text")
|
|
858
|
-
log_debug "$label: ~$tokens tokens (~$((tokens * 4)) chars)"
|
|
859
|
-
}
|
|
860
|
-
|
|
861
838
|
# =============================================================================
|
|
862
839
|
# RESPONSE BUILDERS (v2.4)
|
|
863
840
|
# =============================================================================
|
|
@@ -1316,39 +1293,6 @@ process_consultant_response() {
|
|
|
1316
1293
|
return $exit_code
|
|
1317
1294
|
}
|
|
1318
1295
|
|
|
1319
|
-
# Check if a consultant is enabled
|
|
1320
|
-
# Usage: is_consultant_enabled <consultant_name>
|
|
1321
|
-
# Returns: 0 if enabled, 1 if disabled
|
|
1322
|
-
is_consultant_enabled() {
|
|
1323
|
-
local name="$1"
|
|
1324
|
-
local name_upper
|
|
1325
|
-
name_upper=$(to_upper "$name")
|
|
1326
|
-
local var_name="ENABLE_${name_upper}"
|
|
1327
|
-
|
|
1328
|
-
# Get default based on consultant type
|
|
1329
|
-
local default="true"
|
|
1330
|
-
case "$name_upper" in
|
|
1331
|
-
GLM|DEEPSEEK)
|
|
1332
|
-
default="false"
|
|
1333
|
-
;;
|
|
1334
|
-
esac
|
|
1335
|
-
|
|
1336
|
-
[[ "${!var_name:-$default}" == "true" ]]
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
# Get list of enabled consultants
|
|
1340
|
-
# Usage: get_enabled_consultants
|
|
1341
|
-
# Output: Space-separated list of enabled consultant names
|
|
1342
|
-
get_enabled_consultants() {
|
|
1343
|
-
local enabled=()
|
|
1344
|
-
for consultant in "${ALL_CONSULTANTS[@]}"; do
|
|
1345
|
-
if is_consultant_enabled "$consultant"; then
|
|
1346
|
-
enabled+=("$consultant")
|
|
1347
|
-
fi
|
|
1348
|
-
done
|
|
1349
|
-
echo "${enabled[@]}"
|
|
1350
|
-
}
|
|
1351
|
-
|
|
1352
1296
|
# =============================================================================
|
|
1353
1297
|
# SYNTHESIS CLI RESOLUTION (v2.10.1)
|
|
1354
1298
|
# =============================================================================
|
package/scripts/lib/costs.sh
CHANGED
|
@@ -650,23 +650,6 @@ generate_cost_report() {
|
|
|
650
650
|
jq -r '.sessions | .[-5:] | .[] | " \(.timestamp): \(.id) - $\(.cost)"' "$COST_TRACKING_FILE" 2>/dev/null || echo " No sessions"
|
|
651
651
|
}
|
|
652
652
|
|
|
653
|
-
# =============================================================================
|
|
654
|
-
# UTILITY
|
|
655
|
-
# =============================================================================
|
|
656
|
-
|
|
657
|
-
# Convert tokens to estimated cost (quick helper)
|
|
658
|
-
# Usage: tokens_to_cost <tokens> [model]
|
|
659
|
-
tokens_to_cost() {
|
|
660
|
-
local tokens="$1"
|
|
661
|
-
local model="${2:-default}"
|
|
662
|
-
|
|
663
|
-
# Assume 60/40 split
|
|
664
|
-
local input=$((tokens * 60 / 100))
|
|
665
|
-
local output=$((tokens * 40 / 100))
|
|
666
|
-
|
|
667
|
-
estimate_query_cost "$model" "$input" "$output"
|
|
668
|
-
}
|
|
669
|
-
|
|
670
653
|
# =============================================================================
|
|
671
654
|
# RESPONSE LENGTH LIMITS (v2.3)
|
|
672
655
|
# =============================================================================
|
package/scripts/lib/personas.sh
CHANGED
|
@@ -159,16 +159,6 @@ PERSONA_CATALOG="
|
|
|
159
159
|
# CATALOG FUNCTIONS
|
|
160
160
|
# =============================================================================
|
|
161
161
|
|
|
162
|
-
# List all available personas
|
|
163
|
-
# Usage: list_personas
|
|
164
|
-
list_personas() {
|
|
165
|
-
echo "Available Personas:"
|
|
166
|
-
echo ""
|
|
167
|
-
echo "$PERSONA_CATALOG" | grep -v '^$' | while IFS='|' read -r id name var desc; do
|
|
168
|
-
printf " %2s) %-22s - %s\n" "$id" "$name" "$desc"
|
|
169
|
-
done
|
|
170
|
-
}
|
|
171
|
-
|
|
172
162
|
# Get persona info by ID
|
|
173
163
|
# Usage: get_persona_by_id <id> [field]
|
|
174
164
|
# Fields: name, var, desc, all (default: all)
|
|
@@ -331,14 +321,6 @@ get_persona_name() {
|
|
|
331
321
|
echo "External Consultant"
|
|
332
322
|
}
|
|
333
323
|
|
|
334
|
-
# Get persona ID for a consultant (for configuration display)
|
|
335
|
-
# Usage: get_persona_id "Gemini"
|
|
336
|
-
get_persona_id() {
|
|
337
|
-
local upper
|
|
338
|
-
upper=$(_normalize_name "$1")
|
|
339
|
-
_resolve_persona_id "$upper"
|
|
340
|
-
}
|
|
341
|
-
|
|
342
324
|
# Build complete system prompt with persona + output format
|
|
343
325
|
# Usage: build_system_prompt "Gemini"
|
|
344
326
|
build_system_prompt() {
|
|
@@ -107,26 +107,3 @@ get_consultant_reliability() {
|
|
|
107
107
|
| if $a > 0 then (($s * 100) / $a | floor) else -1 end' \
|
|
108
108
|
"$RELIABILITY_FILE" 2>/dev/null || echo "-1"
|
|
109
109
|
}
|
|
110
|
-
|
|
111
|
-
# Format a short human-readable reliability report, sorted by success% asc.
|
|
112
|
-
# Usage: format_reliability_report
|
|
113
|
-
format_reliability_report() {
|
|
114
|
-
if [[ ! -f "$RELIABILITY_FILE" ]]; then
|
|
115
|
-
echo "No reliability data available"
|
|
116
|
-
return
|
|
117
|
-
fi
|
|
118
|
-
|
|
119
|
-
echo " Consultant | Attempts | Success%"
|
|
120
|
-
echo " ---------------------|----------|---------"
|
|
121
|
-
jq -r '
|
|
122
|
-
.consultants
|
|
123
|
-
| to_entries
|
|
124
|
-
| map({name: .key, attempts: (.value.attempts // 0), successes: (.value.successes // 0)})
|
|
125
|
-
| map(. + {rate: (if .attempts > 0 then (((.successes * 100) / .attempts) | floor) else -1 end)})
|
|
126
|
-
| sort_by(.rate)
|
|
127
|
-
| .[]
|
|
128
|
-
| " \(.name)|\(.attempts)|\(.rate)"
|
|
129
|
-
' "$RELIABILITY_FILE" 2>/dev/null | while IFS='|' read -r name attempts rate; do
|
|
130
|
-
printf " %-20s | %-8s | %s%%\n" "$name" "$attempts" "$rate"
|
|
131
|
-
done
|
|
132
|
-
}
|
package/scripts/lib/routing.sh
CHANGED
|
@@ -194,34 +194,6 @@ select_consultants() {
|
|
|
194
194
|
done
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
# Get the list of consultants as JSON
|
|
198
|
-
# Usage: get_selected_consultants_json <category> [min_affinity]
|
|
199
|
-
get_selected_consultants_json() {
|
|
200
|
-
local category="$1"
|
|
201
|
-
local min_affinity="${2:-7}"
|
|
202
|
-
|
|
203
|
-
local consultants
|
|
204
|
-
consultants=$(select_consultants "$category" "$min_affinity")
|
|
205
|
-
local json="["
|
|
206
|
-
local first=true
|
|
207
|
-
|
|
208
|
-
while IFS= read -r c; do
|
|
209
|
-
if [[ -n "$c" ]]; then
|
|
210
|
-
local score
|
|
211
|
-
score=$(get_affinity "$category" "$c")
|
|
212
|
-
if [[ "$first" == "true" ]]; then
|
|
213
|
-
first=false
|
|
214
|
-
else
|
|
215
|
-
json+=","
|
|
216
|
-
fi
|
|
217
|
-
json+="{\"consultant\":\"$c\",\"affinity\":$score}"
|
|
218
|
-
fi
|
|
219
|
-
done <<< "$consultants"
|
|
220
|
-
|
|
221
|
-
json+="]"
|
|
222
|
-
echo "$json"
|
|
223
|
-
}
|
|
224
|
-
|
|
225
197
|
# Check if a consultant is recommended for a category
|
|
226
198
|
# Usage: is_recommended <category> <consultant> [min_affinity]
|
|
227
199
|
is_recommended() {
|
|
@@ -236,77 +208,36 @@ is_recommended() {
|
|
|
236
208
|
return 1
|
|
237
209
|
}
|
|
238
210
|
|
|
239
|
-
#
|
|
240
|
-
#
|
|
241
|
-
# =============================================================================
|
|
242
|
-
|
|
243
|
-
# Determine the routing mode based on the category
|
|
244
|
-
# Usage: get_routing_mode <category>
|
|
245
|
-
# Returns: full|selective|single
|
|
211
|
+
# Backward-compatible routing utilities. The orchestrator selects directly by
|
|
212
|
+
# affinity; these helpers remain for users that source routing.sh.
|
|
246
213
|
get_routing_mode() {
|
|
247
214
|
local category="$1"
|
|
248
|
-
|
|
249
215
|
case "$category" in
|
|
250
|
-
SECURITY)
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
QUICK_SYNTAX)
|
|
255
|
-
# Syntax: just one needed
|
|
256
|
-
echo "single"
|
|
257
|
-
;;
|
|
258
|
-
CODE_REVIEW|BUG_DEBUG|ARCHITECTURE)
|
|
259
|
-
# Important: at least 3
|
|
260
|
-
echo "selective"
|
|
261
|
-
;;
|
|
262
|
-
*)
|
|
263
|
-
# Default: all
|
|
264
|
-
echo "full"
|
|
265
|
-
;;
|
|
216
|
+
SECURITY) echo "full" ;;
|
|
217
|
+
QUICK_SYNTAX) echo "single" ;;
|
|
218
|
+
CODE_REVIEW|BUG_DEBUG|ARCHITECTURE) echo "selective" ;;
|
|
219
|
+
*) echo "full" ;;
|
|
266
220
|
esac
|
|
267
221
|
}
|
|
268
222
|
|
|
269
|
-
# Get the recommended number of consultants
|
|
270
|
-
# Usage: get_recommended_count <category>
|
|
271
223
|
get_recommended_count() {
|
|
272
|
-
local
|
|
273
|
-
|
|
274
|
-
|
|
224
|
+
local mode
|
|
225
|
+
mode=$(get_routing_mode "$1")
|
|
275
226
|
case "$mode" in
|
|
276
|
-
full)
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
echo 5 # Subset based on affinity
|
|
281
|
-
;;
|
|
282
|
-
single)
|
|
283
|
-
echo 1
|
|
284
|
-
;;
|
|
285
|
-
*)
|
|
286
|
-
echo 10
|
|
287
|
-
;;
|
|
227
|
+
full) echo 10 ;;
|
|
228
|
+
selective) echo 5 ;;
|
|
229
|
+
single) echo 1 ;;
|
|
230
|
+
*) echo 10 ;;
|
|
288
231
|
esac
|
|
289
232
|
}
|
|
290
233
|
|
|
291
|
-
# =============================================================================
|
|
292
|
-
# TIMEOUT ADJUSTMENTS
|
|
293
|
-
# =============================================================================
|
|
294
|
-
|
|
295
|
-
# Get recommended timeout for a category
|
|
296
|
-
# Usage: get_category_timeout <category>
|
|
297
234
|
get_category_timeout() {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
CODE_REVIEW) echo 180 ;;
|
|
305
|
-
ALGORITHM) echo 180 ;;
|
|
306
|
-
DATABASE) echo 120 ;;
|
|
307
|
-
API_DESIGN) echo 180 ;;
|
|
308
|
-
TESTING) echo 120 ;;
|
|
309
|
-
GENERAL|*) echo 180 ;;
|
|
235
|
+
case "$1" in
|
|
236
|
+
QUICK_SYNTAX) echo 60 ;;
|
|
237
|
+
BUG_DEBUG|CODE_REVIEW|ALGORITHM|API_DESIGN) echo 180 ;;
|
|
238
|
+
ARCHITECTURE|SECURITY) echo 240 ;;
|
|
239
|
+
DATABASE|TESTING) echo 120 ;;
|
|
240
|
+
GENERAL|*) echo 180 ;;
|
|
310
241
|
esac
|
|
311
242
|
}
|
|
312
243
|
|
|
@@ -345,14 +276,12 @@ select_consultants_cost_aware() {
|
|
|
345
276
|
|
|
346
277
|
# Simple queries: only economic models, fewer consultants
|
|
347
278
|
if [[ $complexity -le $simple_threshold ]]; then
|
|
348
|
-
# For simple queries, use only 2 consultants with economic models
|
|
349
279
|
select_consultants "$category" "$min_affinity" 2
|
|
350
280
|
return
|
|
351
281
|
fi
|
|
352
282
|
|
|
353
283
|
# Medium complexity: balanced selection
|
|
354
284
|
if [[ $complexity -le $medium_threshold ]]; then
|
|
355
|
-
# Use standard selection but limit to 3-4 consultants
|
|
356
285
|
select_consultants "$category" "$min_affinity" 4
|
|
357
286
|
return
|
|
358
287
|
fi
|
|
@@ -395,36 +324,6 @@ get_cost_aware_model() {
|
|
|
395
324
|
echo ""
|
|
396
325
|
}
|
|
397
326
|
|
|
398
|
-
# Check if cost-aware routing is enabled
|
|
399
|
-
# Usage: is_cost_aware_routing_enabled
|
|
400
|
-
is_cost_aware_routing_enabled() {
|
|
401
|
-
[[ "${ENABLE_COST_AWARE_ROUTING:-false}" == "true" ]]
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
# Get routing summary for logging
|
|
405
|
-
# Usage: get_routing_summary <category> <complexity> <num_consultants>
|
|
406
|
-
get_routing_summary() {
|
|
407
|
-
local category="$1"
|
|
408
|
-
local complexity="${2:-5}"
|
|
409
|
-
local num_consultants="${3:-5}"
|
|
410
|
-
|
|
411
|
-
local mode="standard"
|
|
412
|
-
if is_cost_aware_routing_enabled; then
|
|
413
|
-
local simple_threshold="${COMPLEXITY_THRESHOLD_SIMPLE:-3}"
|
|
414
|
-
local medium_threshold="${COMPLEXITY_THRESHOLD_MEDIUM:-6}"
|
|
415
|
-
|
|
416
|
-
if [[ $complexity -le $simple_threshold ]]; then
|
|
417
|
-
mode="economic"
|
|
418
|
-
elif [[ $complexity -le $medium_threshold ]]; then
|
|
419
|
-
mode="balanced"
|
|
420
|
-
else
|
|
421
|
-
mode="comprehensive"
|
|
422
|
-
fi
|
|
423
|
-
fi
|
|
424
|
-
|
|
425
|
-
echo "{\"category\":\"$category\",\"complexity\":$complexity,\"mode\":\"$mode\",\"consultants\":$num_consultants}"
|
|
426
|
-
}
|
|
427
|
-
|
|
428
327
|
# =============================================================================
|
|
429
328
|
# FALLBACK ESCALATION (v2.3 Quality Review)
|
|
430
329
|
# =============================================================================
|