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.
- package/.claude/commands/ai-consultants:consult.md +94 -0
- package/.claude/commands/ai-consultants:debate.md +103 -0
- package/.claude/commands/ai-consultants:help.md +30 -0
- package/CLAUDE.md +839 -0
- package/LICENSE +21 -0
- package/README.md +758 -0
- package/SKILL.md +156 -0
- package/bin/ai-consultants +96 -0
- package/docs/COST_RATES.md +172 -0
- package/docs/JSON_SCHEMA.md +305 -0
- package/docs/SETUP.md +879 -0
- package/docs/SMART_ROUTING.md +219 -0
- package/docs/cost_rates.json +143 -0
- package/package.json +47 -0
- package/references/configuration.md +141 -0
- package/references/details.md +60 -0
- package/scripts/build_context.sh +562 -0
- package/scripts/classify_question.sh +148 -0
- package/scripts/config.sh +753 -0
- package/scripts/configure.sh +1093 -0
- package/scripts/consult_all.sh +934 -0
- package/scripts/debate_round.sh +421 -0
- package/scripts/doctor.sh +642 -0
- package/scripts/followup.sh +197 -0
- package/scripts/install.sh +319 -0
- package/scripts/lib/api.sh +640 -0
- package/scripts/lib/api_query.sh +228 -0
- package/scripts/lib/cache.sh +338 -0
- package/scripts/lib/chunking.sh +880 -0
- package/scripts/lib/code_optimizer.sh +671 -0
- package/scripts/lib/common.sh +1088 -0
- package/scripts/lib/costs.sh +674 -0
- package/scripts/lib/personas.sh +372 -0
- package/scripts/lib/progress.sh +251 -0
- package/scripts/lib/reflection.sh +447 -0
- package/scripts/lib/routing.sh +566 -0
- package/scripts/lib/schema.json +165 -0
- package/scripts/lib/session.sh +327 -0
- package/scripts/lib/symbol_map.sh +445 -0
- package/scripts/lib/voting.sh +495 -0
- package/scripts/peer_review.sh +460 -0
- package/scripts/preflight_check.sh +452 -0
- package/scripts/query_aider.sh +83 -0
- package/scripts/query_amp.sh +67 -0
- package/scripts/query_claude.sh +99 -0
- package/scripts/query_codex.sh +92 -0
- package/scripts/query_cursor.sh +72 -0
- package/scripts/query_deepseek.sh +17 -0
- package/scripts/query_gemini.sh +85 -0
- package/scripts/query_glm.sh +17 -0
- package/scripts/query_grok.sh +17 -0
- package/scripts/query_kilo.sh +140 -0
- package/scripts/query_kimi.sh +67 -0
- package/scripts/query_minimax.sh +17 -0
- package/scripts/query_mistral.sh +97 -0
- package/scripts/query_ollama.sh +328 -0
- package/scripts/query_qwen3.sh +93 -0
- package/scripts/setup_wizard.sh +367 -0
- package/scripts/skillport-install.sh +196 -0
- package/scripts/synthesize.sh +332 -0
- package/templates/consultation_report.md +323 -0
- package/templates/synthesis_prompt.md +120 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# personas.sh - Consultant personality definitions for AI Consultants v2.0
|
|
3
|
+
#
|
|
4
|
+
# Each consultant has a unique persona that shapes their response style:
|
|
5
|
+
# - Gemini: The Architect - Focus on design, scalability, enterprise patterns
|
|
6
|
+
# - Codex: The Pragmatist - Focus on simplicity, quick wins, proven solutions
|
|
7
|
+
# - Mistral: The Devil's Advocate - Actively seeks problems, edge cases, risks
|
|
8
|
+
# - Kilo: The Innovator - Creative solutions, unconventional approaches
|
|
9
|
+
# - Cursor: The Integrator - Full-stack perspective, cross-cutting concerns
|
|
10
|
+
|
|
11
|
+
# =============================================================================
|
|
12
|
+
# PERSONA DEFINITIONS
|
|
13
|
+
# =============================================================================
|
|
14
|
+
|
|
15
|
+
# System prompt prefix for Gemini - The Architect (token-optimized v2.1)
|
|
16
|
+
PERSONA_GEMINI='Role: The Architect. Focus: scalable design, enterprise patterns, modularity, performance, security.
|
|
17
|
+
Priorities: long-term maintainability, industry standards, separation of concerns.
|
|
18
|
+
Always address: scaling trade-offs, integration points, architectural impact.'
|
|
19
|
+
|
|
20
|
+
# System prompt prefix for Codex - The Pragmatist (token-optimized v2.1)
|
|
21
|
+
PERSONA_CODEX='Role: The Pragmatist. Focus: simplicity, quick wins, proven solutions, clean code.
|
|
22
|
+
Priorities: YAGNI, readability, incremental implementation, battle-tested approaches.
|
|
23
|
+
Always prefer: simplest working solution, avoiding over-engineering and premature optimization.'
|
|
24
|
+
|
|
25
|
+
# System prompt prefix for Mistral - The Devil's Advocate (token-optimized v2.1)
|
|
26
|
+
PERSONA_MISTRAL='Role: The Devil'\''s Advocate. Focus: finding problems, edge cases, security vulnerabilities, risks.
|
|
27
|
+
Priorities: challenge assumptions, identify failure scenarios, expose technical debt.
|
|
28
|
+
Always ask: what could go wrong? unvalidated assumptions? single points of failure? attack vectors?'
|
|
29
|
+
|
|
30
|
+
# System prompt prefix for Kilo - The Innovator (token-optimized v2.1)
|
|
31
|
+
PERSONA_KILO='Role: The Innovator. Focus: creative solutions, emerging tech, unconventional approaches.
|
|
32
|
+
Priorities: elegant simplification, modern patterns, bold ideas, alternative paradigms.
|
|
33
|
+
Always explore: novel approaches others overlook, ways to rethink the problem, future trends.'
|
|
34
|
+
|
|
35
|
+
# System prompt prefix for Cursor - The Integrator (token-optimized v2.1)
|
|
36
|
+
PERSONA_CURSOR='Role: The Integrator. Focus: full-stack perspective, cross-cutting concerns, system-wide consistency.
|
|
37
|
+
Priorities: logging/monitoring/error handling, frontend-backend integration, developer experience.
|
|
38
|
+
Always consider: system-wide impact, integration points, testing across layers, onboarding.'
|
|
39
|
+
|
|
40
|
+
# System prompt prefix for Aider - The Pair Programmer (token-optimized v2.1)
|
|
41
|
+
PERSONA_AIDER='Role: The Pair Programmer. Focus: collaborative coding, step-by-step implementation, code organization.
|
|
42
|
+
Priorities: clear explanations, atomic commits, git-aware changes, reviewable diffs.
|
|
43
|
+
Always: explain changes, keep code clean, make small incremental steps.'
|
|
44
|
+
|
|
45
|
+
# System prompt prefix for Claude - The Synthesizer (token-optimized v2.2)
|
|
46
|
+
PERSONA_CLAUDE='Role: The Synthesizer. Focus: big picture thinking, connecting ideas across domains, distilling complexity.
|
|
47
|
+
Priorities: coherent synthesis, holistic understanding, actionable insights, nuanced analysis.
|
|
48
|
+
Always: see connections others miss, bridge different perspectives, provide clear summaries.'
|
|
49
|
+
|
|
50
|
+
# System prompt prefix for Amp - The Systems Thinker (token-optimized v2.8)
|
|
51
|
+
PERSONA_AMP='Role: The Systems Thinker. Focus: holistic system design, component interactions, emergent behaviors.
|
|
52
|
+
Priorities: understand dependencies, identify feedback loops, predict cascading effects.
|
|
53
|
+
Always consider: how parts interact, system boundaries, resilience patterns, failure propagation.'
|
|
54
|
+
|
|
55
|
+
# System prompt prefix for Kimi - The Eastern Sage (token-optimized v2.9)
|
|
56
|
+
PERSONA_KIMI='Role: The Eastern Sage. Focus: holistic understanding, balance of perspectives, wisdom from diverse viewpoints.
|
|
57
|
+
Priorities: consider multiple angles, find harmony in contradictions, synthesize Eastern and Western approaches.
|
|
58
|
+
Always seek: deeper patterns, balanced solutions, wisdom that transcends immediate technical concerns.'
|
|
59
|
+
|
|
60
|
+
# System prompt prefix for Qwen3 - The Analyst (API-based, token-optimized v2.1)
|
|
61
|
+
PERSONA_QWEN3='Role: The Analyst. Focus: data-driven decisions, pattern recognition, performance profiling.
|
|
62
|
+
Priorities: measurable outcomes, quantitative comparisons, evidence-based recommendations.
|
|
63
|
+
Always provide: metrics, benchmarks, statistical reasoning, data-backed trade-offs.'
|
|
64
|
+
|
|
65
|
+
# System prompt prefix for GLM - The Methodologist (API-based, token-optimized v2.1)
|
|
66
|
+
PERSONA_GLM='Role: The Methodologist. Focus: systematic approaches, structured problem-solving, process standardization.
|
|
67
|
+
Priorities: clear procedural steps, verification checkpoints, edge case coverage.
|
|
68
|
+
Always emphasize: reproducible workflows, documentation of assumptions, validation criteria.'
|
|
69
|
+
|
|
70
|
+
# System prompt prefix for Grok - The Provocateur (API-based, token-optimized v2.1)
|
|
71
|
+
PERSONA_GROK='Role: The Provocateur. Focus: challenging conventions, radical alternatives, paradigm shifts.
|
|
72
|
+
Priorities: question "best practices", expose hidden complexity, break rules when beneficial.
|
|
73
|
+
Always consider: why conventional approach might be wrong, hidden costs of following the crowd.'
|
|
74
|
+
|
|
75
|
+
# System prompt prefix for DeepSeek - The Code Specialist (API-based, token-optimized v2.1)
|
|
76
|
+
PERSONA_DEEPSEEK='Role: The Code Specialist. Focus: code generation, algorithm design, multi-language best practices.
|
|
77
|
+
Priorities: clean efficient code, right data structures, language-specific idioms.
|
|
78
|
+
Always provide: working code examples, reasoning behind implementation choices.'
|
|
79
|
+
|
|
80
|
+
# System prompt prefix for MiniMax - The Pragmatic Optimizer (API-based, token-optimized v2.10)
|
|
81
|
+
PERSONA_MINIMAX='Role: The Pragmatic Optimizer. Focus: practical efficiency, performance optimization, real-world constraints.
|
|
82
|
+
Priorities: measurable results, avoiding over-engineering, quick implementations, cost-effectiveness.
|
|
83
|
+
Always consider: performance impact, memory usage, implementation complexity vs benefit.'
|
|
84
|
+
|
|
85
|
+
# System prompt prefix for The Mentor (token-optimized v2.1)
|
|
86
|
+
PERSONA_MENTOR='Role: The Mentor. Focus: teaching, knowledge transfer, building understanding.
|
|
87
|
+
Priorities: explain why not just how, build mental models, identify learning opportunities.
|
|
88
|
+
Always: progress from simple to complex, highlight common pitfalls, empower future problem-solving.'
|
|
89
|
+
|
|
90
|
+
# System prompt prefix for The Optimizer (token-optimized v2.1)
|
|
91
|
+
PERSONA_OPTIMIZER='Role: The Optimizer. Focus: performance, efficiency, bottleneck identification.
|
|
92
|
+
Priorities: time/space complexity, memory patterns, caching strategies, parallelization.
|
|
93
|
+
Always analyze: CPU/memory/IO characteristics, performance vs readability trade-offs, profiling strategies.'
|
|
94
|
+
|
|
95
|
+
# System prompt prefix for The Security Expert (token-optimized v2.1)
|
|
96
|
+
PERSONA_SECURITY='Role: The Security Expert. Focus: threat modeling, attack surface analysis, secure coding.
|
|
97
|
+
Priorities: input validation, auth patterns, defense in depth, least privilege.
|
|
98
|
+
Always evaluate: OWASP Top 10, data exposure, crypto choices, compliance requirements.'
|
|
99
|
+
|
|
100
|
+
# System prompt prefix for The Minimalist (token-optimized v2.1)
|
|
101
|
+
PERSONA_MINIMALIST='Role: The Minimalist. Focus: eliminating complexity, questioning every abstraction.
|
|
102
|
+
Priorities: prefer deletion over addition, simplest working solution, code that fits in your head.
|
|
103
|
+
Always ask: what can we remove? is this earning its complexity? are we solving the right problem?'
|
|
104
|
+
|
|
105
|
+
# System prompt prefix for The DX Advocate (token-optimized v2.1)
|
|
106
|
+
PERSONA_DX='Role: The DX Advocate. Focus: developer experience, intuitive APIs, helpful error messages.
|
|
107
|
+
Priorities: reduce friction, guide developers to solutions, smooth onboarding paths.
|
|
108
|
+
Always consider: learning curves, common mistakes prevention, IDE support, debugging experience.'
|
|
109
|
+
|
|
110
|
+
# System prompt prefix for The Debugger (token-optimized v2.1)
|
|
111
|
+
PERSONA_DEBUGGER='Role: The Debugger. Focus: root cause analysis, systematic hypothesis testing, log interpretation.
|
|
112
|
+
Priorities: reproduce-isolate-fix methodology, identify real problem vs symptoms.
|
|
113
|
+
Always ask: what changed? can we reproduce? what do logs say? which assumptions are wrong?'
|
|
114
|
+
|
|
115
|
+
# System prompt prefix for The Reviewer (token-optimized v2.1)
|
|
116
|
+
PERSONA_REVIEWER='Role: The Reviewer. Focus: code quality, project conventions, constructive feedback.
|
|
117
|
+
Priorities: maintainability, test coverage, documentation completeness, future developer experience.
|
|
118
|
+
Always evaluate: follows patterns? easy to modify? edge cases handled? intent clear? new team member perspective?'
|
|
119
|
+
|
|
120
|
+
# =============================================================================
|
|
121
|
+
# OUTPUT FORMAT INSTRUCTION
|
|
122
|
+
# =============================================================================
|
|
123
|
+
|
|
124
|
+
# Instruction to force structured JSON output with confidence (token-optimized v2.1)
|
|
125
|
+
OUTPUT_FORMAT_INSTRUCTION='Respond ONLY in valid JSON:
|
|
126
|
+
{"response":{"summary":"<2-3 sentences max 500 chars>","detailed":"<full response>","approach":"<name>","pros":[],"cons":[],"caveats":[]},"confidence":{"score":<1-10>,"reasoning":"<why>"}}
|
|
127
|
+
Score: 1-3=uncertain, 4-6=moderate, 7-9=confident, 10=certain.
|
|
128
|
+
Optional fields: code_snippets[{language,code,description}], alternatives[{name,reason_not_chosen}], uncertainty_factors[].
|
|
129
|
+
No text outside JSON.'
|
|
130
|
+
|
|
131
|
+
# =============================================================================
|
|
132
|
+
# PERSONA CATALOG
|
|
133
|
+
# =============================================================================
|
|
134
|
+
|
|
135
|
+
# Complete catalog of available personas
|
|
136
|
+
# Format: ID|Name|Variable|Short description
|
|
137
|
+
PERSONA_CATALOG="
|
|
138
|
+
1|The Architect|PERSONA_GEMINI|Design patterns, scalability, enterprise
|
|
139
|
+
2|The Pragmatist|PERSONA_CODEX|Simplicity, quick wins, proven solutions
|
|
140
|
+
3|The Devil's Advocate|PERSONA_MISTRAL|Edge cases, risks, security
|
|
141
|
+
4|The Innovator|PERSONA_KILO|Creative solutions, new technologies
|
|
142
|
+
5|The Integrator|PERSONA_CURSOR|Full-stack, cross-cutting concerns
|
|
143
|
+
6|The Analyst|PERSONA_QWEN3|Data-driven, metrics, performance
|
|
144
|
+
7|The Methodologist|PERSONA_GLM|Structured approaches, processes
|
|
145
|
+
8|The Provocateur|PERSONA_GROK|Challenge conventions, radical alternatives
|
|
146
|
+
9|The Mentor|PERSONA_MENTOR|Teaching, explanations, learning focus
|
|
147
|
+
10|The Optimizer|PERSONA_OPTIMIZER|Performance, efficiency, resource usage
|
|
148
|
+
11|The Security Expert|PERSONA_SECURITY|Security-first, vulnerabilities, hardening
|
|
149
|
+
12|The Minimalist|PERSONA_MINIMALIST|Less is more, essential features only
|
|
150
|
+
13|The DX Advocate|PERSONA_DX|Developer experience, ergonomics, tooling
|
|
151
|
+
14|The Debugger|PERSONA_DEBUGGER|Root cause analysis, troubleshooting
|
|
152
|
+
15|The Reviewer|PERSONA_REVIEWER|Code review, best practices, quality
|
|
153
|
+
16|The Pair Programmer|PERSONA_AIDER|Collaborative coding, step-by-step
|
|
154
|
+
17|The Code Specialist|PERSONA_DEEPSEEK|Code generation, algorithms, multi-language
|
|
155
|
+
18|The Synthesizer|PERSONA_CLAUDE|Big picture, connecting ideas, synthesis
|
|
156
|
+
19|The Systems Thinker|PERSONA_AMP|System design, interactions, emergent behavior
|
|
157
|
+
20|The Eastern Sage|PERSONA_KIMI|Holistic understanding, balanced perspectives
|
|
158
|
+
21|The Pragmatic Optimizer|PERSONA_MINIMAX|Performance, efficiency, pragmatism
|
|
159
|
+
"
|
|
160
|
+
|
|
161
|
+
# =============================================================================
|
|
162
|
+
# CATALOG FUNCTIONS
|
|
163
|
+
# =============================================================================
|
|
164
|
+
|
|
165
|
+
# List all available personas
|
|
166
|
+
# Usage: list_personas
|
|
167
|
+
list_personas() {
|
|
168
|
+
echo "Available Personas:"
|
|
169
|
+
echo ""
|
|
170
|
+
echo "$PERSONA_CATALOG" | grep -v '^$' | while IFS='|' read -r id name var desc; do
|
|
171
|
+
printf " %2s) %-22s - %s\n" "$id" "$name" "$desc"
|
|
172
|
+
done
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
# Get persona info by ID
|
|
176
|
+
# Usage: get_persona_by_id <id> [field]
|
|
177
|
+
# Fields: name, var, desc, all (default: all)
|
|
178
|
+
get_persona_by_id() {
|
|
179
|
+
local id="$1"
|
|
180
|
+
local field="${2:-all}"
|
|
181
|
+
|
|
182
|
+
local match
|
|
183
|
+
match=$(echo "$PERSONA_CATALOG" | grep "^${id}|" | head -1)
|
|
184
|
+
|
|
185
|
+
if [[ -z "$match" ]]; then
|
|
186
|
+
return 1
|
|
187
|
+
fi
|
|
188
|
+
|
|
189
|
+
case "$field" in
|
|
190
|
+
name) echo "$match" | cut -d'|' -f2 ;;
|
|
191
|
+
var) echo "$match" | cut -d'|' -f3 ;;
|
|
192
|
+
desc) echo "$match" | cut -d'|' -f4 ;;
|
|
193
|
+
all) echo "$match" ;;
|
|
194
|
+
esac
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
# Get persona ID by name
|
|
198
|
+
# Usage: get_persona_id_by_name "The Architect"
|
|
199
|
+
get_persona_id_by_name() {
|
|
200
|
+
local name="$1"
|
|
201
|
+
local match
|
|
202
|
+
match=$(echo "$PERSONA_CATALOG" | grep "|${name}|" | head -1)
|
|
203
|
+
|
|
204
|
+
if [[ -n "$match" ]]; then
|
|
205
|
+
echo "$match" | cut -d'|' -f1
|
|
206
|
+
else
|
|
207
|
+
return 1
|
|
208
|
+
fi
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
# Get persona prompt content by ID
|
|
212
|
+
# Usage: get_persona_content_by_id <id>
|
|
213
|
+
get_persona_content_by_id() {
|
|
214
|
+
local id="$1"
|
|
215
|
+
local var_name
|
|
216
|
+
var_name=$(get_persona_by_id "$id" "var")
|
|
217
|
+
|
|
218
|
+
if [[ -n "$var_name" ]]; then
|
|
219
|
+
echo "${!var_name}"
|
|
220
|
+
else
|
|
221
|
+
return 1
|
|
222
|
+
fi
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
# =============================================================================
|
|
226
|
+
# HELPER FUNCTIONS
|
|
227
|
+
# =============================================================================
|
|
228
|
+
|
|
229
|
+
# Internal lookup table for agent defaults (maps agent to default persona ID)
|
|
230
|
+
_AGENT_DEFAULT_PERSONAS="
|
|
231
|
+
GEMINI|1
|
|
232
|
+
CODEX|2
|
|
233
|
+
MISTRAL|3
|
|
234
|
+
KILO|4
|
|
235
|
+
CURSOR|5
|
|
236
|
+
AIDER|16
|
|
237
|
+
AMP|19
|
|
238
|
+
KIMI|20
|
|
239
|
+
CLAUDE|18
|
|
240
|
+
QWEN3|6
|
|
241
|
+
GLM|17
|
|
242
|
+
GROK|8
|
|
243
|
+
DEEPSEEK|7
|
|
244
|
+
MINIMAX|21
|
|
245
|
+
"
|
|
246
|
+
|
|
247
|
+
# Internal: Resolve persona ID for a consultant
|
|
248
|
+
# Returns the effective persona ID (explicit, or default)
|
|
249
|
+
# Usage: _resolve_persona_id "GEMINI"
|
|
250
|
+
_resolve_persona_id() {
|
|
251
|
+
local upper="$1"
|
|
252
|
+
|
|
253
|
+
# Check explicit persona ID
|
|
254
|
+
local persona_id_var="${upper}_PERSONA_ID"
|
|
255
|
+
local persona_id="${!persona_id_var:-}"
|
|
256
|
+
if [[ -n "$persona_id" ]]; then
|
|
257
|
+
echo "$persona_id"
|
|
258
|
+
return 0
|
|
259
|
+
fi
|
|
260
|
+
|
|
261
|
+
# Check default
|
|
262
|
+
local default_match
|
|
263
|
+
default_match=$(echo "$_AGENT_DEFAULT_PERSONAS" | grep "^${upper}|" | head -1)
|
|
264
|
+
if [[ -n "$default_match" ]]; then
|
|
265
|
+
echo "$default_match" | cut -d'|' -f2
|
|
266
|
+
return 0
|
|
267
|
+
fi
|
|
268
|
+
|
|
269
|
+
return 1
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
# Internal: Normalize consultant name to uppercase
|
|
273
|
+
_normalize_name() {
|
|
274
|
+
echo "$1" | tr '[:lower:]' '[:upper:]' | tr -d ' -'
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
# Get the persona prompt for a specific consultant
|
|
278
|
+
# Usage: get_persona "Gemini"
|
|
279
|
+
# Priority: 1) {AGENT}_PERSONA_ID, 2) {AGENT}_PERSONA, 3) default from catalog
|
|
280
|
+
get_persona() {
|
|
281
|
+
local consultant="$1"
|
|
282
|
+
local upper
|
|
283
|
+
upper=$(_normalize_name "$consultant")
|
|
284
|
+
|
|
285
|
+
# Check for explicit persona ID first
|
|
286
|
+
local persona_id
|
|
287
|
+
persona_id=$(_resolve_persona_id "$upper")
|
|
288
|
+
if [[ -n "$persona_id" ]]; then
|
|
289
|
+
local content
|
|
290
|
+
content=$(get_persona_content_by_id "$persona_id")
|
|
291
|
+
if [[ -n "$content" ]]; then
|
|
292
|
+
echo "$content"
|
|
293
|
+
return
|
|
294
|
+
fi
|
|
295
|
+
fi
|
|
296
|
+
|
|
297
|
+
# Check for custom persona text
|
|
298
|
+
local persona_var="${upper}_PERSONA"
|
|
299
|
+
local custom_persona="${!persona_var:-}"
|
|
300
|
+
if [[ -n "$custom_persona" ]]; then
|
|
301
|
+
echo "$custom_persona"
|
|
302
|
+
return
|
|
303
|
+
fi
|
|
304
|
+
|
|
305
|
+
# Fallback: generic persona
|
|
306
|
+
echo "You are an AI consultant providing expert technical advice.
|
|
307
|
+
Focus on clarity, accuracy, and actionable recommendations.
|
|
308
|
+
Consider trade-offs and provide balanced analysis."
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
# Get persona name/title for a consultant
|
|
312
|
+
# Usage: get_persona_name "Gemini"
|
|
313
|
+
get_persona_name() {
|
|
314
|
+
local consultant="$1"
|
|
315
|
+
local upper
|
|
316
|
+
upper=$(_normalize_name "$consultant")
|
|
317
|
+
|
|
318
|
+
# Check for explicit persona ID
|
|
319
|
+
local persona_id
|
|
320
|
+
persona_id=$(_resolve_persona_id "$upper")
|
|
321
|
+
if [[ -n "$persona_id" ]]; then
|
|
322
|
+
local name
|
|
323
|
+
name=$(get_persona_by_id "$persona_id" "name")
|
|
324
|
+
if [[ -n "$name" ]]; then
|
|
325
|
+
echo "$name"
|
|
326
|
+
return
|
|
327
|
+
fi
|
|
328
|
+
fi
|
|
329
|
+
|
|
330
|
+
# Check for custom persona name
|
|
331
|
+
local name_var="${upper}_PERSONA_NAME"
|
|
332
|
+
local custom_name="${!name_var:-}"
|
|
333
|
+
if [[ -n "$custom_name" ]]; then
|
|
334
|
+
echo "$custom_name"
|
|
335
|
+
return
|
|
336
|
+
fi
|
|
337
|
+
|
|
338
|
+
echo "External Consultant"
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
# Get persona ID for a consultant (for configuration display)
|
|
342
|
+
# Usage: get_persona_id "Gemini"
|
|
343
|
+
get_persona_id() {
|
|
344
|
+
local upper
|
|
345
|
+
upper=$(_normalize_name "$1")
|
|
346
|
+
_resolve_persona_id "$upper"
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
# Build complete system prompt with persona + output format
|
|
350
|
+
# Usage: build_system_prompt "Gemini"
|
|
351
|
+
build_system_prompt() {
|
|
352
|
+
local consultant="$1"
|
|
353
|
+
local persona=$(get_persona "$consultant")
|
|
354
|
+
|
|
355
|
+
echo "${persona}
|
|
356
|
+
|
|
357
|
+
${OUTPUT_FORMAT_INSTRUCTION}"
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
# Build complete query with system prompt prepended
|
|
361
|
+
# Usage: build_query_with_persona "Gemini" "original query"
|
|
362
|
+
build_query_with_persona() {
|
|
363
|
+
local consultant="$1"
|
|
364
|
+
local query="$2"
|
|
365
|
+
local system_prompt=$(build_system_prompt "$consultant")
|
|
366
|
+
|
|
367
|
+
echo "# System Instructions
|
|
368
|
+
${system_prompt}
|
|
369
|
+
|
|
370
|
+
# User Query
|
|
371
|
+
${query}"
|
|
372
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# progress.sh - Progress bars and interactive display for AI Consultants v2.0
|
|
3
|
+
#
|
|
4
|
+
# Shows progress bars for each consultant during consultations.
|
|
5
|
+
|
|
6
|
+
# =============================================================================
|
|
7
|
+
# CONFIGURATION
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
# Characters for progress bar
|
|
11
|
+
BAR_FILLED="█"
|
|
12
|
+
BAR_EMPTY="░"
|
|
13
|
+
BAR_WIDTH=20
|
|
14
|
+
|
|
15
|
+
# Colors (ANSI)
|
|
16
|
+
COLOR_RESET="\033[0m"
|
|
17
|
+
COLOR_GREEN="\033[0;32m"
|
|
18
|
+
COLOR_YELLOW="\033[0;33m"
|
|
19
|
+
COLOR_RED="\033[0;31m"
|
|
20
|
+
COLOR_BLUE="\033[0;34m"
|
|
21
|
+
COLOR_CYAN="\033[0;36m"
|
|
22
|
+
COLOR_DIM="\033[0;90m"
|
|
23
|
+
|
|
24
|
+
# =============================================================================
|
|
25
|
+
# PROGRESS STATE
|
|
26
|
+
# =============================================================================
|
|
27
|
+
# Using map_* functions from common.sh for bash 3.2 compatibility
|
|
28
|
+
# Maps: PROGRESS_PERCENT, PROGRESS_STATUS, PROGRESS_START_TIME
|
|
29
|
+
|
|
30
|
+
# Initialize progress for a consultant
|
|
31
|
+
# Usage: init_progress <consultant>
|
|
32
|
+
init_progress() {
|
|
33
|
+
local consultant="$1"
|
|
34
|
+
map_set "PROGRESS_PERCENT" "$consultant" "0"
|
|
35
|
+
map_set "PROGRESS_STATUS" "$consultant" "starting"
|
|
36
|
+
map_set "PROGRESS_START_TIME" "$consultant" "$(date +%s)"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# Update progress
|
|
40
|
+
# Usage: update_progress <consultant> <percent> [status]
|
|
41
|
+
update_progress() {
|
|
42
|
+
local consultant="$1"
|
|
43
|
+
local percent="$2"
|
|
44
|
+
local status="${3:-running}"
|
|
45
|
+
|
|
46
|
+
map_set "PROGRESS_PERCENT" "$consultant" "$percent"
|
|
47
|
+
map_set "PROGRESS_STATUS" "$consultant" "$status"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# =============================================================================
|
|
51
|
+
# DISPLAY FUNCTIONS
|
|
52
|
+
# =============================================================================
|
|
53
|
+
|
|
54
|
+
# Generate progress bar string
|
|
55
|
+
# Usage: generate_bar <percent>
|
|
56
|
+
generate_bar() {
|
|
57
|
+
local percent=$1
|
|
58
|
+
local filled=$((percent * BAR_WIDTH / 100))
|
|
59
|
+
local empty=$((BAR_WIDTH - filled))
|
|
60
|
+
|
|
61
|
+
local bar=""
|
|
62
|
+
for ((i=0; i<filled; i++)); do
|
|
63
|
+
bar+="$BAR_FILLED"
|
|
64
|
+
done
|
|
65
|
+
for ((i=0; i<empty; i++)); do
|
|
66
|
+
bar+="$BAR_EMPTY"
|
|
67
|
+
done
|
|
68
|
+
|
|
69
|
+
echo "$bar"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# Get status icon
|
|
73
|
+
# Usage: get_status_icon <status>
|
|
74
|
+
get_status_icon() {
|
|
75
|
+
local status="$1"
|
|
76
|
+
case "$status" in
|
|
77
|
+
starting) echo "⏳" ;;
|
|
78
|
+
running) echo "🔄" ;;
|
|
79
|
+
success) echo "✅" ;;
|
|
80
|
+
failed) echo "❌" ;;
|
|
81
|
+
timeout) echo "⏰" ;;
|
|
82
|
+
skipped) echo "⏭️" ;;
|
|
83
|
+
*) echo "❓" ;;
|
|
84
|
+
esac
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# Get color for status
|
|
88
|
+
# Usage: get_status_color <status>
|
|
89
|
+
get_status_color() {
|
|
90
|
+
local status="$1"
|
|
91
|
+
case "$status" in
|
|
92
|
+
success) echo "$COLOR_GREEN" ;;
|
|
93
|
+
failed|timeout) echo "$COLOR_RED" ;;
|
|
94
|
+
running) echo "$COLOR_BLUE" ;;
|
|
95
|
+
starting) echo "$COLOR_YELLOW" ;;
|
|
96
|
+
*) echo "$COLOR_RESET" ;;
|
|
97
|
+
esac
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# Calculate elapsed time
|
|
101
|
+
# Usage: get_elapsed <consultant>
|
|
102
|
+
get_elapsed() {
|
|
103
|
+
local consultant="$1"
|
|
104
|
+
local start
|
|
105
|
+
start=$(map_get "PROGRESS_START_TIME" "$consultant")
|
|
106
|
+
start="${start:-$(date +%s)}"
|
|
107
|
+
local now=$(date +%s)
|
|
108
|
+
local elapsed=$((now - start))
|
|
109
|
+
echo "${elapsed}s"
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# Render a single progress line
|
|
113
|
+
# Usage: render_progress_line <consultant>
|
|
114
|
+
render_progress_line() {
|
|
115
|
+
local consultant="$1"
|
|
116
|
+
local percent status
|
|
117
|
+
percent=$(map_get "PROGRESS_PERCENT" "$consultant")
|
|
118
|
+
percent="${percent:-0}"
|
|
119
|
+
status=$(map_get "PROGRESS_STATUS" "$consultant")
|
|
120
|
+
status="${status:-starting}"
|
|
121
|
+
|
|
122
|
+
local bar=$(generate_bar "$percent")
|
|
123
|
+
local icon=$(get_status_icon "$status")
|
|
124
|
+
local color=$(get_status_color "$status")
|
|
125
|
+
local elapsed=$(get_elapsed "$consultant")
|
|
126
|
+
|
|
127
|
+
printf " ${color}[%-8s]${COLOR_RESET} %s %3d%% %s ${COLOR_DIM}(%s)${COLOR_RESET}\n" \
|
|
128
|
+
"$consultant" "$bar" "$percent" "$icon" "$elapsed"
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
# Render all progress bars
|
|
132
|
+
# Usage: render_all_progress
|
|
133
|
+
render_all_progress() {
|
|
134
|
+
local consultants=("Gemini" "Codex" "Mistral" "Kilo" "Cursor")
|
|
135
|
+
|
|
136
|
+
echo ""
|
|
137
|
+
echo " Progress:"
|
|
138
|
+
echo ""
|
|
139
|
+
|
|
140
|
+
for c in "${consultants[@]}"; do
|
|
141
|
+
local status
|
|
142
|
+
status=$(map_get "PROGRESS_STATUS" "$c")
|
|
143
|
+
if [[ -n "$status" ]]; then
|
|
144
|
+
render_progress_line "$c"
|
|
145
|
+
fi
|
|
146
|
+
done
|
|
147
|
+
|
|
148
|
+
echo ""
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
# Update display in-place (for terminals that support ANSI)
|
|
152
|
+
# Usage: update_display
|
|
153
|
+
update_display() {
|
|
154
|
+
# Save cursor position, move up, render, restore
|
|
155
|
+
local num_lines=6 # Header + 4 consultants + footer
|
|
156
|
+
|
|
157
|
+
# Move cursor up
|
|
158
|
+
printf "\033[${num_lines}A"
|
|
159
|
+
|
|
160
|
+
# Clear lines and re-render
|
|
161
|
+
for ((i=0; i<num_lines; i++)); do
|
|
162
|
+
printf "\033[2K" # Clear line
|
|
163
|
+
printf "\033[1B" # Move down
|
|
164
|
+
done
|
|
165
|
+
|
|
166
|
+
# Move back up
|
|
167
|
+
printf "\033[${num_lines}A"
|
|
168
|
+
|
|
169
|
+
# Render
|
|
170
|
+
render_all_progress
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
# =============================================================================
|
|
174
|
+
# SPINNER
|
|
175
|
+
# =============================================================================
|
|
176
|
+
|
|
177
|
+
SPINNER_CHARS=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
|
|
178
|
+
SPINNER_INDEX=0
|
|
179
|
+
|
|
180
|
+
# Advance spinner
|
|
181
|
+
spin() {
|
|
182
|
+
SPINNER_INDEX=$(( (SPINNER_INDEX + 1) % ${#SPINNER_CHARS[@]} ))
|
|
183
|
+
echo "${SPINNER_CHARS[$SPINNER_INDEX]}"
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
# Show spinner with message
|
|
187
|
+
# Usage: show_spinner <message>
|
|
188
|
+
show_spinner() {
|
|
189
|
+
local message="$1"
|
|
190
|
+
printf "\r %s %s" "$(spin)" "$message"
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
# =============================================================================
|
|
194
|
+
# SUMMARY DISPLAY
|
|
195
|
+
# =============================================================================
|
|
196
|
+
|
|
197
|
+
# Show final summary
|
|
198
|
+
# Usage: show_summary <success_count> <total_count> <total_time>
|
|
199
|
+
show_summary() {
|
|
200
|
+
local success="$1"
|
|
201
|
+
local total="$2"
|
|
202
|
+
local time="$3"
|
|
203
|
+
|
|
204
|
+
echo ""
|
|
205
|
+
echo "╔══════════════════════════════════════════════════════════════╗"
|
|
206
|
+
echo "║ Consultation Summary ║"
|
|
207
|
+
echo "╚══════════════════════════════════════════════════════════════╝"
|
|
208
|
+
echo ""
|
|
209
|
+
printf " Consultants: ${COLOR_GREEN}%d${COLOR_RESET}/%d successful\n" "$success" "$total"
|
|
210
|
+
printf " Total time: ${COLOR_CYAN}%s${COLOR_RESET}\n" "$time"
|
|
211
|
+
echo ""
|
|
212
|
+
|
|
213
|
+
# Details per consultant
|
|
214
|
+
for c in Gemini Codex Mistral Kilo Cursor; do
|
|
215
|
+
local status
|
|
216
|
+
status=$(map_get "PROGRESS_STATUS" "$c")
|
|
217
|
+
if [[ -n "$status" ]]; then
|
|
218
|
+
local icon=$(get_status_icon "$status")
|
|
219
|
+
local elapsed=$(get_elapsed "$c")
|
|
220
|
+
printf " %s %-8s: %s (%s)\n" "$icon" "$c" "$status" "$elapsed"
|
|
221
|
+
fi
|
|
222
|
+
done
|
|
223
|
+
|
|
224
|
+
echo ""
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
# =============================================================================
|
|
228
|
+
# INTERACTIVE MODE HELPERS
|
|
229
|
+
# =============================================================================
|
|
230
|
+
|
|
231
|
+
# Show header for interactive consultation
|
|
232
|
+
show_consultation_header() {
|
|
233
|
+
local question="$1"
|
|
234
|
+
local truncated="${question:0:60}"
|
|
235
|
+
[[ ${#question} -gt 60 ]] && truncated+="..."
|
|
236
|
+
|
|
237
|
+
echo ""
|
|
238
|
+
echo "╔══════════════════════════════════════════════════════════════╗"
|
|
239
|
+
echo "║ AI Consultants v2.0 - Live Consultation ║"
|
|
240
|
+
echo "╚══════════════════════════════════════════════════════════════╝"
|
|
241
|
+
echo ""
|
|
242
|
+
echo " Query: $truncated"
|
|
243
|
+
echo ""
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
# Show early termination option message
|
|
247
|
+
show_early_termination_hint() {
|
|
248
|
+
echo ""
|
|
249
|
+
echo " ${COLOR_DIM}Press Ctrl+C to stop early with available responses${COLOR_RESET}"
|
|
250
|
+
echo ""
|
|
251
|
+
}
|