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,165 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "AI Consultant Response Schema v2.0",
4
+ "description": "Unified output schema for all AI consultants in ai-consultants skill",
5
+ "type": "object",
6
+ "required": ["consultant", "response", "confidence", "metadata"],
7
+ "properties": {
8
+ "consultant": {
9
+ "type": "string",
10
+ "description": "Name of the consultant (Gemini, Codex, Mistral, Kilo, Cursor, Aider, Amp, Kimi, Claude, Qwen3, GLM, Grok, DeepSeek, MiniMax, Ollama)",
11
+ "enum": ["Gemini", "Codex", "Mistral", "Kilo", "Cursor", "Aider", "Amp", "Kimi", "Claude", "Qwen3", "GLM", "Grok", "DeepSeek", "MiniMax", "Ollama"]
12
+ },
13
+ "model": {
14
+ "type": "string",
15
+ "description": "Specific model version used"
16
+ },
17
+ "persona": {
18
+ "type": "string",
19
+ "description": "Assigned persona role",
20
+ "enum": ["The Architect", "The Pragmatist", "The Devil's Advocate", "The Innovator", "The Integrator", "The Pair Programmer", "The Systems Thinker", "The Eastern Sage", "The Synthesizer", "The Analyst", "The Methodologist", "The Provocateur", "The Code Specialist", "The Pragmatic Optimizer", "The Local Expert"]
21
+ },
22
+ "response": {
23
+ "type": "object",
24
+ "required": ["summary", "detailed", "approach"],
25
+ "properties": {
26
+ "summary": {
27
+ "type": "string",
28
+ "description": "TL;DR in 2-3 sentences (max 500 chars)",
29
+ "maxLength": 500
30
+ },
31
+ "detailed": {
32
+ "type": "string",
33
+ "description": "Full detailed response"
34
+ },
35
+ "approach": {
36
+ "type": "string",
37
+ "description": "High-level approach name/category"
38
+ },
39
+ "code_snippets": {
40
+ "type": "array",
41
+ "description": "Code examples if applicable",
42
+ "items": {
43
+ "type": "object",
44
+ "properties": {
45
+ "language": { "type": "string" },
46
+ "code": { "type": "string" },
47
+ "description": { "type": "string" }
48
+ }
49
+ }
50
+ },
51
+ "pros": {
52
+ "type": "array",
53
+ "description": "Advantages of the proposed solution",
54
+ "items": { "type": "string" }
55
+ },
56
+ "cons": {
57
+ "type": "array",
58
+ "description": "Disadvantages or trade-offs",
59
+ "items": { "type": "string" }
60
+ },
61
+ "alternatives": {
62
+ "type": "array",
63
+ "description": "Alternative approaches considered",
64
+ "items": {
65
+ "type": "object",
66
+ "properties": {
67
+ "name": { "type": "string" },
68
+ "reason_not_chosen": { "type": "string" }
69
+ }
70
+ }
71
+ },
72
+ "caveats": {
73
+ "type": "array",
74
+ "description": "Important assumptions or limitations",
75
+ "items": { "type": "string" }
76
+ },
77
+ "references": {
78
+ "type": "array",
79
+ "description": "Links or references if applicable",
80
+ "items": { "type": "string" }
81
+ }
82
+ }
83
+ },
84
+ "confidence": {
85
+ "type": "object",
86
+ "required": ["score", "reasoning"],
87
+ "properties": {
88
+ "score": {
89
+ "type": "integer",
90
+ "description": "Confidence score from 1-10",
91
+ "minimum": 1,
92
+ "maximum": 10
93
+ },
94
+ "reasoning": {
95
+ "type": "string",
96
+ "description": "Why this confidence level was assigned"
97
+ },
98
+ "uncertainty_factors": {
99
+ "type": "array",
100
+ "description": "Factors that reduce confidence",
101
+ "items": { "type": "string" }
102
+ }
103
+ }
104
+ },
105
+ "debate": {
106
+ "type": "object",
107
+ "description": "Data for multi-agent debate rounds",
108
+ "properties": {
109
+ "round": {
110
+ "type": "integer",
111
+ "description": "Current debate round (1, 2, or 3)"
112
+ },
113
+ "position_changed": {
114
+ "type": "boolean",
115
+ "description": "Whether position changed from previous round"
116
+ },
117
+ "critiques": {
118
+ "type": "array",
119
+ "description": "Critiques of other consultants' responses",
120
+ "items": {
121
+ "type": "object",
122
+ "properties": {
123
+ "target": { "type": "string" },
124
+ "critique": { "type": "string" },
125
+ "severity": { "enum": ["minor", "moderate", "major"] }
126
+ }
127
+ }
128
+ },
129
+ "incorporated_from": {
130
+ "type": "array",
131
+ "description": "Ideas incorporated from other consultants",
132
+ "items": {
133
+ "type": "object",
134
+ "properties": {
135
+ "source": { "type": "string" },
136
+ "idea": { "type": "string" }
137
+ }
138
+ }
139
+ }
140
+ }
141
+ },
142
+ "metadata": {
143
+ "type": "object",
144
+ "properties": {
145
+ "tokens_used": {
146
+ "type": "integer",
147
+ "description": "Approximate tokens consumed"
148
+ },
149
+ "latency_ms": {
150
+ "type": "integer",
151
+ "description": "Response time in milliseconds"
152
+ },
153
+ "model_version": {
154
+ "type": "string",
155
+ "description": "Exact model version string"
156
+ },
157
+ "timestamp": {
158
+ "type": "string",
159
+ "format": "date-time",
160
+ "description": "ISO 8601 timestamp of response"
161
+ }
162
+ }
163
+ }
164
+ }
165
+ }
@@ -0,0 +1,327 @@
1
+ #!/bin/bash
2
+ # session.sh - Session state management for AI Consultants v2.0
3
+ #
4
+ # Manages session state to support follow-up queries
5
+ # and maintain context between successive consultations.
6
+
7
+ # =============================================================================
8
+ # CONFIGURATION
9
+ # =============================================================================
10
+
11
+ # Directory for session files
12
+ SESSION_DIR="${SESSION_DIR:-/tmp/ai_consultants_sessions}"
13
+ SESSION_FILE="${SESSION_DIR}/current_session.json"
14
+ SESSION_HISTORY_FILE="${SESSION_DIR}/history.json"
15
+
16
+ # Create directory with secure permissions (owner-only access)
17
+ if [[ ! -d "$SESSION_DIR" ]]; then
18
+ mkdir -p "$SESSION_DIR" 2>/dev/null || true
19
+ fi
20
+ chmod 700 "$SESSION_DIR" 2>/dev/null || true
21
+
22
+ # =============================================================================
23
+ # SESSION MANAGEMENT
24
+ # =============================================================================
25
+
26
+ # Generate new session ID
27
+ # Usage: generate_session_id
28
+ generate_session_id() {
29
+ echo "session_$(date +%Y%m%d_%H%M%S)_$$"
30
+ }
31
+
32
+ # Save current session
33
+ # Usage: save_session <session_id> <query> <responses_dir> [category]
34
+ save_session() {
35
+ local session_id="$1"
36
+ local query="$2"
37
+ local responses_dir="$3"
38
+ local category="${4:-GENERAL}"
39
+
40
+ local timestamp=$(date -Iseconds)
41
+
42
+ # Create file with secure permissions before writing
43
+ touch "$SESSION_FILE"
44
+ chmod 600 "$SESSION_FILE"
45
+
46
+ jq -n \
47
+ --arg id "$session_id" \
48
+ --arg query "$query" \
49
+ --arg dir "$responses_dir" \
50
+ --arg category "$category" \
51
+ --arg timestamp "$timestamp" \
52
+ '{
53
+ id: $id,
54
+ query: $query,
55
+ responses_dir: $dir,
56
+ category: $category,
57
+ timestamp: $timestamp,
58
+ follow_ups: []
59
+ }' > "$SESSION_FILE"
60
+
61
+ # Add to history
62
+ add_to_history "$session_id" "$query" "$responses_dir" "$category"
63
+
64
+ echo "$session_id"
65
+ }
66
+
67
+ # Get current session
68
+ # Usage: get_current_session
69
+ get_current_session() {
70
+ if [[ -f "$SESSION_FILE" ]]; then
71
+ cat "$SESSION_FILE"
72
+ else
73
+ echo "{}"
74
+ fi
75
+ }
76
+
77
+ # Check if an active session exists
78
+ # Usage: has_active_session
79
+ has_active_session() {
80
+ if [[ -f "$SESSION_FILE" && -s "$SESSION_FILE" ]]; then
81
+ local id=$(jq -r '.id // empty' "$SESSION_FILE" 2>/dev/null)
82
+ [[ -n "$id" ]] && return 0
83
+ fi
84
+ return 1
85
+ }
86
+
87
+ # Get current session ID
88
+ # Usage: get_current_session_id
89
+ get_current_session_id() {
90
+ if has_active_session; then
91
+ jq -r '.id' "$SESSION_FILE"
92
+ else
93
+ echo ""
94
+ fi
95
+ }
96
+
97
+ # Get query from current session
98
+ # Usage: get_current_query
99
+ get_current_query() {
100
+ if has_active_session; then
101
+ jq -r '.query' "$SESSION_FILE"
102
+ else
103
+ echo ""
104
+ fi
105
+ }
106
+
107
+ # Get responses directory from current session
108
+ # Usage: get_current_responses_dir
109
+ get_current_responses_dir() {
110
+ if has_active_session; then
111
+ jq -r '.responses_dir' "$SESSION_FILE"
112
+ else
113
+ echo ""
114
+ fi
115
+ }
116
+
117
+ # =============================================================================
118
+ # FOLLOW-UP MANAGEMENT
119
+ # =============================================================================
120
+
121
+ # Add follow-up to session
122
+ # Usage: add_follow_up <follow_up_query> <follow_up_responses_dir>
123
+ add_follow_up() {
124
+ local follow_up_query="$1"
125
+ local follow_up_dir="$2"
126
+
127
+ if ! has_active_session; then
128
+ return 1
129
+ fi
130
+
131
+ local timestamp=$(date -Iseconds)
132
+
133
+ jq --arg query "$follow_up_query" \
134
+ --arg dir "$follow_up_dir" \
135
+ --arg ts "$timestamp" \
136
+ '.follow_ups += [{query: $query, responses_dir: $dir, timestamp: $ts}]' \
137
+ "$SESSION_FILE" > "${SESSION_FILE}.tmp" && \
138
+ mv "${SESSION_FILE}.tmp" "$SESSION_FILE"
139
+ }
140
+
141
+ # Get number of follow-ups in session
142
+ # Usage: get_follow_up_count
143
+ get_follow_up_count() {
144
+ if has_active_session; then
145
+ jq -r '.follow_ups | length // 0' "$SESSION_FILE"
146
+ else
147
+ echo 0
148
+ fi
149
+ }
150
+
151
+ # =============================================================================
152
+ # SESSION HISTORY
153
+ # =============================================================================
154
+
155
+ # Initialize history file if it doesn't exist
156
+ init_history() {
157
+ if [[ ! -f "$SESSION_HISTORY_FILE" ]]; then
158
+ # Create file with secure permissions before writing
159
+ touch "$SESSION_HISTORY_FILE"
160
+ chmod 600 "$SESSION_HISTORY_FILE"
161
+ echo '{"sessions": []}' > "$SESSION_HISTORY_FILE"
162
+ fi
163
+ }
164
+
165
+ # Add session to history
166
+ # Usage: add_to_history <session_id> <query> <responses_dir> <category>
167
+ add_to_history() {
168
+ local session_id="$1"
169
+ local query="$2"
170
+ local responses_dir="$3"
171
+ local category="$4"
172
+
173
+ init_history
174
+
175
+ local timestamp=$(date -Iseconds)
176
+ local query_preview="${query:0:100}"
177
+
178
+ jq --arg id "$session_id" \
179
+ --arg query "$query_preview" \
180
+ --arg dir "$responses_dir" \
181
+ --arg cat "$category" \
182
+ --arg ts "$timestamp" \
183
+ '.sessions += [{id: $id, query_preview: $query, responses_dir: $dir, category: $cat, timestamp: $ts}]' \
184
+ "$SESSION_HISTORY_FILE" > "${SESSION_HISTORY_FILE}.tmp" && \
185
+ mv "${SESSION_HISTORY_FILE}.tmp" "$SESSION_HISTORY_FILE"
186
+ }
187
+
188
+ # Get last N sessions from history
189
+ # Usage: get_recent_sessions [count]
190
+ get_recent_sessions() {
191
+ local count="${1:-5}"
192
+
193
+ init_history
194
+
195
+ jq --argjson n "$count" '.sessions | .[-$n:]' "$SESSION_HISTORY_FILE"
196
+ }
197
+
198
+ # Search session by ID
199
+ # Usage: get_session_by_id <session_id>
200
+ get_session_by_id() {
201
+ local session_id="$1"
202
+
203
+ init_history
204
+
205
+ jq --arg id "$session_id" '.sessions[] | select(.id == $id)' "$SESSION_HISTORY_FILE"
206
+ }
207
+
208
+ # =============================================================================
209
+ # CONTEXT BUILDING
210
+ # =============================================================================
211
+
212
+ # Build context from session for follow-up
213
+ # Usage: build_follow_up_context <follow_up_instruction>
214
+ build_follow_up_context() {
215
+ local instruction="$1"
216
+
217
+ if ! has_active_session; then
218
+ echo "$instruction"
219
+ return
220
+ fi
221
+
222
+ local session=$(get_current_session)
223
+ local original_query=$(echo "$session" | jq -r '.query')
224
+ local responses_dir=$(echo "$session" | jq -r '.responses_dir')
225
+
226
+ local context="# Previous Session Context
227
+
228
+ ## Original Question
229
+ $original_query
230
+
231
+ ## Consultant Responses
232
+ "
233
+
234
+ # Add response summaries
235
+ if [[ -d "$responses_dir" ]]; then
236
+ for f in "$responses_dir"/*.json; do
237
+ if [[ -f "$f" ]]; then
238
+ local consultant=$(jq -r '.consultant // "Unknown"' "$f" 2>/dev/null)
239
+ local summary=$(jq -r '.response.summary // "No summary"' "$f" 2>/dev/null)
240
+ local approach=$(jq -r '.response.approach // "unknown"' "$f" 2>/dev/null)
241
+
242
+ context+="
243
+ ### $consultant
244
+ Approach: $approach
245
+ Summary: $summary
246
+ "
247
+ fi
248
+ done
249
+ fi
250
+
251
+ # Add any previous follow-ups
252
+ local follow_up_count=$(get_follow_up_count)
253
+ if [[ $follow_up_count -gt 0 ]]; then
254
+ context+="
255
+ ## Previous Follow-ups
256
+ "
257
+ echo "$session" | jq -r '.follow_ups[] | "- \(.query)"' >> /dev/null 2>&1 && \
258
+ context+="$(echo "$session" | jq -r '.follow_ups[] | "- \(.query)"')"
259
+ fi
260
+
261
+ context+="
262
+
263
+ # New Request
264
+ $instruction"
265
+
266
+ echo "$context"
267
+ }
268
+
269
+ # =============================================================================
270
+ # CLEANUP
271
+ # =============================================================================
272
+
273
+ # Clear current session
274
+ # Usage: clear_current_session
275
+ clear_current_session() {
276
+ rm -f "$SESSION_FILE"
277
+ }
278
+
279
+ # Clean up sessions older than N days
280
+ # Usage: cleanup_old_sessions [days]
281
+ cleanup_old_sessions() {
282
+ local days="${1:-7}"
283
+
284
+ # Clean up old output files
285
+ # Note: $days must be quoted to prevent injection via specially crafted days value
286
+ find /tmp/ai_consultations -type d -mtime +"$days" -exec rm -rf {} \; 2>/dev/null || true
287
+
288
+ # Remove old sessions from history
289
+ init_history
290
+
291
+ local cutoff=$(date -d "-$days days" -Iseconds 2>/dev/null || date -v-${days}d -Iseconds 2>/dev/null || echo "")
292
+
293
+ if [[ -n "$cutoff" ]]; then
294
+ jq --arg cutoff "$cutoff" '.sessions |= [.[] | select(.timestamp > $cutoff)]' \
295
+ "$SESSION_HISTORY_FILE" > "${SESSION_HISTORY_FILE}.tmp" && \
296
+ mv "${SESSION_HISTORY_FILE}.tmp" "$SESSION_HISTORY_FILE"
297
+ fi
298
+ }
299
+
300
+ # =============================================================================
301
+ # DISPLAY
302
+ # =============================================================================
303
+
304
+ # Show current session info
305
+ # Usage: show_session_info
306
+ show_session_info() {
307
+ if ! has_active_session; then
308
+ echo "No active session"
309
+ return
310
+ fi
311
+
312
+ local session=$(get_current_session)
313
+ local id=$(echo "$session" | jq -r '.id')
314
+ local query=$(echo "$session" | jq -r '.query')
315
+ local timestamp=$(echo "$session" | jq -r '.timestamp')
316
+ local follow_ups=$(echo "$session" | jq -r '.follow_ups | length')
317
+
318
+ echo "╔══════════════════════════════════════════════════════════════╗"
319
+ echo "║ Current Session ║"
320
+ echo "╚══════════════════════════════════════════════════════════════╝"
321
+ echo ""
322
+ echo " ID: $id"
323
+ echo " Query: ${query:0:50}..."
324
+ echo " Started: $timestamp"
325
+ echo " Follow-ups: $follow_ups"
326
+ echo ""
327
+ }