ai-consultants 3.0.0 → 3.2.0
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 +15 -7
- package/CLAUDE.md +33 -6
- package/README.md +20 -7
- package/SKILL.md +5 -4
- package/docs/COST_RATES.md +3 -3
- package/docs/RECIPES.md +6 -3
- package/docs/SETUP.md +6 -2
- package/docs/cost_rates.json +11 -7
- package/docs/releases/v3.1.0.md +95 -0
- package/docs/releases/v3.1.1.md +54 -0
- package/docs/releases/v3.2.0.md +96 -0
- package/package.json +1 -1
- package/references/configuration.md +24 -4
- package/scripts/config.sh +31 -10
- package/scripts/configure.sh +54 -7
- package/scripts/doctor.sh +17 -13
- package/scripts/lib/api.sh +6 -2
- package/scripts/lib/api_query.sh +18 -1
- package/scripts/lib/common.sh +16 -12
- package/scripts/lib/costs.sh +17 -7
- package/scripts/query_claude.sh +39 -8
- package/scripts/query_grok.sh +214 -5
- package/scripts/update_clis.sh +3 -1
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Release v3.2.0
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-07-25
|
|
4
|
+
**Type:** Minor — Claude moves to Opus 5 with adaptive-thinking-safe transports and billing
|
|
5
|
+
**Previous:** v3.1.1
|
|
6
|
+
|
|
7
|
+
## Highlights
|
|
8
|
+
|
|
9
|
+
- **Claude now uses `claude-opus-5` as its premium default** across direct configuration, model tiers, documentation, and cost tracking.
|
|
10
|
+
- **Claude CLI costs now come directly from the provider**, including adaptive thinking and cache charges that are absent from the visible answer.
|
|
11
|
+
- **Anthropic API thinking blocks are handled correctly**, and responses truncated by the shared thinking/output budget are rejected instead of synthesized as complete.
|
|
12
|
+
- **Existing generated Opus 4.8 defaults migrate to Opus 5**, while explicit model pins are recorded and preserved.
|
|
13
|
+
- **Opus 4.8 remains supported** for historical responses and intentional overrides.
|
|
14
|
+
|
|
15
|
+
## What's New
|
|
16
|
+
|
|
17
|
+
### Opus 5 premium default
|
|
18
|
+
|
|
19
|
+
The Claude consultant, premium/max/best quality tier, standalone adapter fallback, examples, and cost catalog now use the canonical `claude-opus-5` model ID. Standard and economy tiers remain on Claude Sonnet 4.6 and Haiku 4.5.
|
|
20
|
+
|
|
21
|
+
Opus 5 retains the previous $5 per million input tokens and $25 per million output tokens. The legacy Opus 4.8 rates remain available so historical sessions and pinned installations continue to be priced correctly.
|
|
22
|
+
|
|
23
|
+
### Exact Claude CLI usage and cost
|
|
24
|
+
|
|
25
|
+
Claude CLI mode now requests its JSON result envelope. AI Consultants extracts:
|
|
26
|
+
|
|
27
|
+
- the visible answer from `.result`;
|
|
28
|
+
- measured input, cache, and output usage from `modelUsage`;
|
|
29
|
+
- the provider-reported `costUSD`.
|
|
30
|
+
|
|
31
|
+
The exact provider cost takes precedence over local token-rate reconstruction. This includes adaptive-thinking and cache charges even though those tokens do not appear in the visible answer.
|
|
32
|
+
|
|
33
|
+
### Adaptive-thinking-safe API mode
|
|
34
|
+
|
|
35
|
+
Anthropic responses may place a thinking block before one or more visible text blocks. The parser now collects every visible `type=text` block instead of assuming the first content block contains the answer.
|
|
36
|
+
|
|
37
|
+
The new `CLAUDE_API_MAX_TOKENS` setting defaults to 16,384 tokens. Anthropic counts adaptive thinking and visible output against this shared budget. If the provider returns `stop_reason=max_tokens`, the consultation fails as truncated rather than entering synthesis as a complete response.
|
|
38
|
+
|
|
39
|
+
### Managed configuration migration
|
|
40
|
+
|
|
41
|
+
Older `ai-consultants init` templates wrote the then-current Opus 4.8 default as an ordinary value. Running `ai-consultants configure` now recognizes that exact historical generated default, upgrades it to Opus 5, and records managed provenance.
|
|
42
|
+
|
|
43
|
+
Explicit model choices are written with an `# ai-consultants:pin` marker and survive subsequent configuration refreshes.
|
|
44
|
+
|
|
45
|
+
## Breaking Changes
|
|
46
|
+
|
|
47
|
+
None — this release is backwards-compatible. Opus 4.8 remains selectable and priced.
|
|
48
|
+
|
|
49
|
+
If `CLAUDE_MODEL=claude-opus-4-8` was an intentional unmarked override rather than the generated default, reassert it once after upgrading:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
ai-consultants configure --set CLAUDE_MODEL=claude-opus-4-8
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Upgrade Guide
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# If installed via git clone
|
|
59
|
+
cd ~/.claude/skills/ai-consultants && git pull
|
|
60
|
+
|
|
61
|
+
# If installed via curl | bash
|
|
62
|
+
curl -fsSL https://raw.githubusercontent.com/matteoscurati/ai-consultants/main/scripts/install.sh | bash
|
|
63
|
+
|
|
64
|
+
# If used through npx
|
|
65
|
+
npx ai-consultants@latest "your question"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Refresh persistent configuration so a historical generated Opus 4.8 value migrates:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
ai-consultants configure
|
|
72
|
+
ai-consultants doctor
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
API users may override the shared thinking/output budget if needed:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
ai-consultants configure --set CLAUDE_API_MAX_TOKENS=32768
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Verification
|
|
82
|
+
|
|
83
|
+
- Full repository gate: 17/17 suites
|
|
84
|
+
- Core suite: 299/299 checks
|
|
85
|
+
- Claude CLI JSON/cost regression suite: 6/6 checks
|
|
86
|
+
- Anthropic transport regression suite: 48/48 checks
|
|
87
|
+
- Shellcheck and release-surface validation
|
|
88
|
+
- Live local Claude CLI JSON envelope verified with `claude-opus-5`
|
|
89
|
+
|
|
90
|
+
## Commits
|
|
91
|
+
|
|
92
|
+
- `3963c3c` feat: upgrade Claude consultant to Opus 5
|
|
93
|
+
|
|
94
|
+
## Contributors
|
|
95
|
+
|
|
96
|
+
- Matteo Scurati
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-consultants",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "A harness for every question - a panel of up to 11 AI models that picks its own deliberation strategy per question (convergence, adversarial verification, tournament) and checks its work before answering",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ai-consultants": "bin/ai-consultants"
|
|
@@ -54,6 +54,11 @@ ai-consultants configure --dry-run
|
|
|
54
54
|
Use the hidden interactive credential prompts (or exported environment variables)
|
|
55
55
|
for API keys; command-line arguments may be visible in shell history and process
|
|
56
56
|
inspection.
|
|
57
|
+
Model defaults carry an `# ai-consultants:default` marker. On rewrite,
|
|
58
|
+
`configure` upgrades the historical unmarked
|
|
59
|
+
`CLAUDE_MODEL=claude-opus-4-8` generated default to Opus 5. An explicit model
|
|
60
|
+
override supplied with `--set` is stored with `# ai-consultants:pin`, so
|
|
61
|
+
`--set CLAUDE_MODEL=claude-opus-4-8` keeps the legacy model intentionally.
|
|
57
62
|
The exhaustive parameter contract is [`.env.example`](../.env.example); the
|
|
58
63
|
configurator derives its accepted keys from that template, while
|
|
59
64
|
[`scripts/config.sh`](../scripts/config.sh) remains the runtime source of truth.
|
|
@@ -182,7 +187,7 @@ override it.
|
|
|
182
187
|
|
|
183
188
|
## CLI/API Mode Switching (v2.6+)
|
|
184
189
|
|
|
185
|
-
|
|
190
|
+
Seven consultants support switching between CLI and API mode. **The default is the CLI** for every consultant that has one. Grok additionally falls back to the xAI API after a failed CLI launch when a key is available. When API mode is explicitly enabled, the CLI is not used.
|
|
186
191
|
|
|
187
192
|
**Gemini auto-resolution (v2.15.1):** leave `GEMINI_USE_API` unset and the mode is chosen for you — API mode when `GEMINI_API_KEY` is present (no `agy` install or OAuth needed; ideal for `npx`), CLI mode (`agy`) otherwise. Set `GEMINI_USE_API` explicitly only to force a mode (an explicit value disables auto-detection).
|
|
188
193
|
|
|
@@ -193,6 +198,7 @@ CODEX_USE_API=false # Use OpenAI API instead of codex CLI
|
|
|
193
198
|
CLAUDE_USE_API=false # Use Anthropic API instead of claude CLI
|
|
194
199
|
MISTRAL_USE_API=false # Use Mistral API instead of vibe CLI
|
|
195
200
|
QWEN3_USE_API=false # Use qwen CLI (default) or DashScope API
|
|
201
|
+
GROK_USE_API=false # Use Grok Build (default); API is fallback
|
|
196
202
|
MINIMAX_USE_API=false # Use mmx CLI (default) or MiniMax API
|
|
197
203
|
```
|
|
198
204
|
|
|
@@ -207,7 +213,7 @@ MINIMAX_USE_API=false # Use mmx CLI (default) or MiniMax API
|
|
|
207
213
|
| Qwen3 | `QWEN3_API_KEY` | DashScope API key |
|
|
208
214
|
| MiniMax | `MINIMAX_API_KEY` | MiniMax API key (API mode only; the mmx CLI uses OAuth) |
|
|
209
215
|
| GLM | `GLM_API_KEY` | Required when `ENABLE_GLM=true` |
|
|
210
|
-
| Grok | `GROK_API_KEY` |
|
|
216
|
+
| Grok | `GROK_API_KEY` | xAI API fallback key; Grok Build CLI uses its own login |
|
|
211
217
|
| DeepSeek | `DEEPSEEK_API_KEY` | Required when `ENABLE_DEEPSEEK=true` |
|
|
212
218
|
|
|
213
219
|
## Consultant Toggles and Models
|
|
@@ -220,12 +226,12 @@ ENABLE_MISTRAL=true
|
|
|
220
226
|
ENABLE_CURSOR=true
|
|
221
227
|
ENABLE_KIMI=true # Kimi CLI - The Eastern Sage
|
|
222
228
|
ENABLE_QWEN3=true # Qwen CLI/API - The Analyst
|
|
229
|
+
ENABLE_GROK=true # Grok Build CLI/API fallback - The Provocateur
|
|
223
230
|
ENABLE_MINIMAX=true # MiniMax CLI/API (mmx) - The Pragmatic Optimizer
|
|
224
231
|
ENABLE_CLAUDE=true # Claude CLI - The Synthesizer (auto-excluded under Claude Code)
|
|
225
232
|
|
|
226
233
|
# API-only consultants (off by default - require API keys)
|
|
227
234
|
ENABLE_GLM=false
|
|
228
|
-
ENABLE_GROK=false
|
|
229
235
|
ENABLE_DEEPSEEK=false
|
|
230
236
|
```
|
|
231
237
|
|
|
@@ -234,7 +240,8 @@ ENABLE_DEEPSEEK=false
|
|
|
234
240
|
```bash
|
|
235
241
|
GEMINI_MODEL=Gemini 3.1 Pro (High) # agy CLI display name; API mode uses GEMINI_API_MODEL
|
|
236
242
|
CODEX_MODEL=gpt-5.5
|
|
237
|
-
CLAUDE_MODEL=claude-opus-
|
|
243
|
+
CLAUDE_MODEL=claude-opus-5
|
|
244
|
+
CLAUDE_API_MAX_TOKENS=16384 # API only: adaptive thinking + visible output
|
|
238
245
|
MISTRAL_MODEL=mistral-large-3
|
|
239
246
|
CURSOR_MODEL=composer-2.5
|
|
240
247
|
KIMI_MODEL=kimi-code/k3
|
|
@@ -245,6 +252,19 @@ DEEPSEEK_MODEL=deepseek-v4-pro
|
|
|
245
252
|
MINIMAX_MODEL=MiniMax-M2.7
|
|
246
253
|
```
|
|
247
254
|
|
|
255
|
+
Anthropic counts adaptive thinking and visible response tokens against the same
|
|
256
|
+
`CLAUDE_API_MAX_TOKENS` limit. The default is 16,384; a response that reaches
|
|
257
|
+
that limit is rejected as truncated instead of entering synthesis as a complete
|
|
258
|
+
answer.
|
|
259
|
+
|
|
260
|
+
`GROK_MODEL` is passed explicitly to `grok -m`. The default transport is the
|
|
261
|
+
headless Grok Build CLI using a private `--prompt-file` inside an isolated,
|
|
262
|
+
tool-free strict sandbox. If the CLI is missing, cannot execute, or has no
|
|
263
|
+
usable authentication, the same query and model fall back to `GROK_API_URL`
|
|
264
|
+
when `GROK_API_KEY` is set. Failures after a request launches (including
|
|
265
|
+
timeouts, model errors, and empty output) are returned without API fallback.
|
|
266
|
+
Set `GROK_USE_API=true` only to force the API path.
|
|
267
|
+
|
|
248
268
|
`KIMI_MODEL` is passed directly to `kimi --model`, so `kimi-code/k3` overrides
|
|
249
269
|
any older default stored in the user's Kimi CLI configuration.
|
|
250
270
|
|
package/scripts/config.sh
CHANGED
|
@@ -64,12 +64,12 @@ DEFAULT_OUTPUT_DIR_BASE="${DEFAULT_OUTPUT_DIR_BASE:-${_AI_CONSULTANTS_XDG_CACHE}
|
|
|
64
64
|
# =============================================================================
|
|
65
65
|
# For agents that support both CLI and API mode, set USE_API=true to use API mode.
|
|
66
66
|
# When API mode is enabled, CLI mode is automatically disabled (mutual exclusivity).
|
|
67
|
-
#
|
|
67
|
+
# 7 agents support switching: Gemini, Codex, Claude, Mistral, Qwen3, Grok, MiniMax
|
|
68
68
|
|
|
69
69
|
# Mode switching (true = API, false = CLI). DEFAULT IS CLI — when a consultant
|
|
70
70
|
# has a CLI, the tool uses it; the CLIs are the primary transport (OAuth /
|
|
71
71
|
# subscription, no API key needed). API mode is opt-in only: for CLI-less models
|
|
72
|
-
# (GLM/
|
|
72
|
+
# (GLM/DeepSeek are API-only) or an explicit per-run user
|
|
73
73
|
# choice. Set a switch to true (with its API key) to force API for that agent.
|
|
74
74
|
# GEMINI_USE_API is intentionally NOT defaulted here: it is auto-resolved in the
|
|
75
75
|
# Gemini configuration section below (needs GEMINI_API_KEY / GEMINI_CMD), so an
|
|
@@ -78,6 +78,8 @@ CODEX_USE_API="${CODEX_USE_API:-false}"
|
|
|
78
78
|
CLAUDE_USE_API="${CLAUDE_USE_API:-false}"
|
|
79
79
|
MISTRAL_USE_API="${MISTRAL_USE_API:-false}"
|
|
80
80
|
QWEN3_USE_API="${QWEN3_USE_API:-false}" # Default false to use qwen CLI
|
|
81
|
+
# GROK_USE_API is intentionally resolved in the Grok section: it is CLI-first,
|
|
82
|
+
# but must preserve an API-only installation when Grok Build is unavailable.
|
|
81
83
|
# MINIMAX_USE_API is intentionally NOT defaulted here: it is auto-resolved in the
|
|
82
84
|
# MiniMax configuration section below (needs MINIMAX_API_KEY), so an explicit
|
|
83
85
|
# unset stays distinguishable from an explicit "false" (back-compat for pre-v2.21
|
|
@@ -186,14 +188,32 @@ GLM_FORMAT="${GLM_FORMAT:-openai}"
|
|
|
186
188
|
# API key: Set GLM_API_KEY environment variable
|
|
187
189
|
|
|
188
190
|
# =============================================================================
|
|
189
|
-
# GROK CONFIGURATION - The Provocateur (API
|
|
191
|
+
# GROK CONFIGURATION - The Provocateur (Grok Build CLI + API fallback)
|
|
190
192
|
# =============================================================================
|
|
191
193
|
|
|
194
|
+
GROK_CMD="${GROK_CMD:-grok}"
|
|
192
195
|
GROK_MODEL="${GROK_MODEL:-grok-4.5}"
|
|
193
196
|
GROK_TIMEOUT_SECONDS="${GROK_TIMEOUT:-180}"
|
|
194
197
|
GROK_API_URL="${GROK_API_URL:-https://api.x.ai/v1/chat/completions}"
|
|
195
198
|
GROK_FORMAT="${GROK_FORMAT:-openai}"
|
|
196
|
-
#
|
|
199
|
+
# Grok Build's official credential name is XAI_API_KEY. Keep the historical
|
|
200
|
+
# GROK_API_KEY public contract and accept XAI_API_KEY as its fallback alias.
|
|
201
|
+
GROK_API_KEY="${GROK_API_KEY:-${XAI_API_KEY:-}}"
|
|
202
|
+
export GROK_API_KEY
|
|
203
|
+
|
|
204
|
+
# CLI-first auto-resolution. Existing users can still pin GROK_USE_API=true,
|
|
205
|
+
# while an unpinned setup uses the CLI whenever it is installed and falls back
|
|
206
|
+
# to the API when only a key is available.
|
|
207
|
+
if [[ -z "${GROK_USE_API+x}" ]]; then
|
|
208
|
+
if command -v "$GROK_CMD" >/dev/null 2>&1; then
|
|
209
|
+
GROK_USE_API=false
|
|
210
|
+
elif [[ -n "$GROK_API_KEY" ]]; then
|
|
211
|
+
GROK_USE_API=true
|
|
212
|
+
else
|
|
213
|
+
GROK_USE_API=false
|
|
214
|
+
fi
|
|
215
|
+
fi
|
|
216
|
+
export GROK_USE_API
|
|
197
217
|
|
|
198
218
|
# =============================================================================
|
|
199
219
|
# DEEPSEEK CONFIGURATION - The Methodologist (API-based)
|
|
@@ -251,7 +271,8 @@ KIMI_CMD="${KIMI_CMD:-kimi}"
|
|
|
251
271
|
# CLAUDE CONFIGURATION - The Synthesizer (v2.2)
|
|
252
272
|
# =============================================================================
|
|
253
273
|
|
|
254
|
-
CLAUDE_MODEL="${CLAUDE_MODEL:-claude-opus-
|
|
274
|
+
CLAUDE_MODEL="${CLAUDE_MODEL:-claude-opus-5}"
|
|
275
|
+
CLAUDE_API_MAX_TOKENS="${CLAUDE_API_MAX_TOKENS:-16384}"
|
|
255
276
|
CLAUDE_TIMEOUT_SECONDS="${CLAUDE_TIMEOUT:-240}"
|
|
256
277
|
CLAUDE_CMD="${CLAUDE_CMD:-claude}"
|
|
257
278
|
|
|
@@ -265,10 +286,10 @@ CLAUDE_CMD="${CLAUDE_CMD:-claude}"
|
|
|
265
286
|
ALL_CONSULTANTS=("Gemini" "Codex" "Mistral" "Cursor" "Kimi" "Claude" "Qwen3" "GLM" "Grok" "DeepSeek" "MiniMax")
|
|
266
287
|
|
|
267
288
|
# CLI-based consultants (use CLI tools, some support CLI/API switching)
|
|
268
|
-
CLI_CONSULTANTS=("Gemini" "Codex" "Mistral" "Cursor" "Kimi" "Claude" "Qwen3" "MiniMax")
|
|
289
|
+
CLI_CONSULTANTS=("Gemini" "Codex" "Mistral" "Cursor" "Kimi" "Claude" "Qwen3" "Grok" "MiniMax")
|
|
269
290
|
|
|
270
291
|
# API-only consultants (use HTTP API directly, no CLI available)
|
|
271
|
-
API_CONSULTANTS=("GLM" "
|
|
292
|
+
API_CONSULTANTS=("GLM" "DeepSeek")
|
|
272
293
|
|
|
273
294
|
# =============================================================================
|
|
274
295
|
# ENABLED CONSULTANTS
|
|
@@ -283,11 +304,11 @@ ENABLE_CURSOR="${ENABLE_CURSOR:-true}"
|
|
|
283
304
|
ENABLE_KIMI="${ENABLE_KIMI:-true}" # Kimi Code (v2.9)
|
|
284
305
|
ENABLE_CLAUDE="${ENABLE_CLAUDE:-true}" # Auto-disabled when invoked by Claude Code
|
|
285
306
|
ENABLE_QWEN3="${ENABLE_QWEN3:-true}" # qwen-code CLI (v2.7); API opt-in
|
|
307
|
+
ENABLE_GROK="${ENABLE_GROK:-true}" # Grok Build CLI; API fallback
|
|
286
308
|
ENABLE_MINIMAX="${ENABLE_MINIMAX:-true}" # mmx CLI (v2.21); API opt-in
|
|
287
309
|
|
|
288
310
|
# API-only consultants (disabled by default - require API keys)
|
|
289
311
|
ENABLE_GLM="${ENABLE_GLM:-false}"
|
|
290
|
-
ENABLE_GROK="${ENABLE_GROK:-false}"
|
|
291
312
|
ENABLE_DEEPSEEK="${ENABLE_DEEPSEEK:-false}"
|
|
292
313
|
|
|
293
314
|
# =============================================================================
|
|
@@ -561,7 +582,7 @@ get_model_for_tier() {
|
|
|
561
582
|
case "$tier" in
|
|
562
583
|
premium|max|best)
|
|
563
584
|
case "$consultant" in
|
|
564
|
-
claude) echo "claude-opus-
|
|
585
|
+
claude) echo "claude-opus-5" ;;
|
|
565
586
|
gemini) echo "Gemini 3.1 Pro (High)" ;;
|
|
566
587
|
codex) echo "gpt-5.5" ;;
|
|
567
588
|
mistral) echo "mistral-large-3" ;;
|
|
@@ -758,4 +779,4 @@ EOF
|
|
|
758
779
|
# VERSION
|
|
759
780
|
# =============================================================================
|
|
760
781
|
|
|
761
|
-
AI_CONSULTANTS_VERSION="3.
|
|
782
|
+
AI_CONSULTANTS_VERSION="3.2.0"
|
package/scripts/configure.sh
CHANGED
|
@@ -181,6 +181,25 @@ set_value() {
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
AUTO_MARKER="# ai-consultants:auto"
|
|
184
|
+
DEFAULT_MARKER="# ai-consultants:default"
|
|
185
|
+
PIN_MARKER="# ai-consultants:pin"
|
|
186
|
+
|
|
187
|
+
has_value_marker() {
|
|
188
|
+
local file="$1" key="$2" marker="$3" line normalized
|
|
189
|
+
[[ -r "$file" ]] || return 1
|
|
190
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
191
|
+
line="${line%$'\r'}"
|
|
192
|
+
[[ "$line" =~ ^[[:space:]]*# ]] && continue
|
|
193
|
+
normalized="${line#"${line%%[![:space:]]*}"}"
|
|
194
|
+
if [[ "$normalized" =~ ^export[[:space:]]+ ]]; then
|
|
195
|
+
normalized="${normalized#export}"
|
|
196
|
+
normalized="${normalized#"${normalized%%[![:space:]]*}"}"
|
|
197
|
+
fi
|
|
198
|
+
[[ "$normalized" == "$key="* ]] || continue
|
|
199
|
+
[[ "$normalized" == *"$marker"* ]] && return 0
|
|
200
|
+
done < "$file"
|
|
201
|
+
return 1
|
|
202
|
+
}
|
|
184
203
|
|
|
185
204
|
is_auto_managed_value() {
|
|
186
205
|
local file="$1" key="$2" line normalized raw="" seen=false
|
|
@@ -239,13 +258,33 @@ set_auto_value() {
|
|
|
239
258
|
# Merge existing persistent values first, then current environment overrides.
|
|
240
259
|
while IFS= read -r key; do
|
|
241
260
|
if [[ -f "$OUTPUT_FILE" ]] && value=$(read_value "$OUTPUT_FILE" "$key"); then
|
|
242
|
-
|
|
261
|
+
if has_value_marker "$OUTPUT_FILE" "$key" "$DEFAULT_MARKER"; then
|
|
262
|
+
set_value "$key" "$value $DEFAULT_MARKER"
|
|
263
|
+
elif has_value_marker "$OUTPUT_FILE" "$key" "$PIN_MARKER"; then
|
|
264
|
+
set_value "$key" "$value $PIN_MARKER"
|
|
265
|
+
else
|
|
266
|
+
set_value "$key" "$value"
|
|
267
|
+
fi
|
|
243
268
|
fi
|
|
244
269
|
if [[ -n "${!key+x}" ]]; then
|
|
245
|
-
|
|
270
|
+
if [[ "$key" == *_MODEL ]]; then
|
|
271
|
+
set_value "$key" "${!key} $PIN_MARKER"
|
|
272
|
+
else
|
|
273
|
+
set_value "$key" "${!key}"
|
|
274
|
+
fi
|
|
246
275
|
fi
|
|
247
276
|
done < <(list_parameters)
|
|
248
277
|
|
|
278
|
+
# Before model defaults had provenance markers, `init` copied the then-current
|
|
279
|
+
# Claude default as an ordinary-looking value. Refresh that exact historical
|
|
280
|
+
# default when configure rewrites the file. A real legacy pin is preserved by
|
|
281
|
+
# `--set CLAUDE_MODEL=claude-opus-4-8`, which records the pin marker.
|
|
282
|
+
if [[ "$(read_value "$WORK_FILE" CLAUDE_MODEL 2>/dev/null || true)" == "claude-opus-4-8" ]] \
|
|
283
|
+
&& ! has_value_marker "$WORK_FILE" CLAUDE_MODEL "$PIN_MARKER"; then
|
|
284
|
+
set_value CLAUDE_MODEL "claude-opus-5 $DEFAULT_MARKER"
|
|
285
|
+
echo "Migrated managed Claude default: claude-opus-4-8 -> claude-opus-5" >&2
|
|
286
|
+
fi
|
|
287
|
+
|
|
249
288
|
configure_cli_only() {
|
|
250
289
|
local enable_key="$1" cmd_key="$2" cmd enabled=false
|
|
251
290
|
cmd=$(effective_input_value "$cmd_key")
|
|
@@ -307,9 +346,9 @@ run_auto_detection() {
|
|
|
307
346
|
configure_cli_only ENABLE_KIMI KIMI_CMD
|
|
308
347
|
configure_switchable ENABLE_CLAUDE CLAUDE_CMD CLAUDE_USE_API ANTHROPIC_API_KEY
|
|
309
348
|
configure_switchable ENABLE_QWEN3 QWEN3_CMD QWEN3_USE_API QWEN3_API_KEY
|
|
349
|
+
configure_switchable ENABLE_GROK GROK_CMD GROK_USE_API GROK_API_KEY
|
|
310
350
|
configure_switchable ENABLE_MINIMAX MINIMAX_CMD MINIMAX_USE_API MINIMAX_API_KEY
|
|
311
351
|
configure_api_only ENABLE_GLM GLM_API_KEY
|
|
312
|
-
configure_api_only ENABLE_GROK GROK_API_KEY
|
|
313
352
|
configure_api_only ENABLE_DEEPSEEK DEEPSEEK_API_KEY
|
|
314
353
|
}
|
|
315
354
|
|
|
@@ -327,7 +366,11 @@ prompt_value() {
|
|
|
327
366
|
else
|
|
328
367
|
read -r -p "$key [$current]: " reply
|
|
329
368
|
if [[ -n "$reply" ]]; then
|
|
330
|
-
|
|
369
|
+
if [[ "$key" == *_MODEL ]]; then
|
|
370
|
+
set_value "$key" "$reply $PIN_MARKER"
|
|
371
|
+
else
|
|
372
|
+
set_value "$key" "$reply"
|
|
373
|
+
fi
|
|
331
374
|
fi
|
|
332
375
|
fi
|
|
333
376
|
}
|
|
@@ -346,7 +389,7 @@ if [[ "$MODE" == "interactive" ]]; then
|
|
|
346
389
|
for key in ENABLE_GEMINI ENABLE_CODEX ENABLE_MISTRAL ENABLE_CURSOR ENABLE_KIMI ENABLE_CLAUDE ENABLE_QWEN3 ENABLE_GLM ENABLE_GROK ENABLE_DEEPSEEK ENABLE_MINIMAX; do
|
|
347
390
|
prompt_value "$key"
|
|
348
391
|
done
|
|
349
|
-
for key in GEMINI_USE_API CODEX_USE_API MISTRAL_USE_API CLAUDE_USE_API QWEN3_USE_API MINIMAX_USE_API; do
|
|
392
|
+
for key in GEMINI_USE_API CODEX_USE_API MISTRAL_USE_API CLAUDE_USE_API QWEN3_USE_API GROK_USE_API MINIMAX_USE_API; do
|
|
350
393
|
prompt_value "$key"
|
|
351
394
|
done
|
|
352
395
|
|
|
@@ -359,7 +402,7 @@ if [[ "$MODE" == "interactive" ]]; then
|
|
|
359
402
|
# parameter name as the user's answer instead.
|
|
360
403
|
while IFS= read -r key <&3; do
|
|
361
404
|
case "$key" in
|
|
362
|
-
ENABLE_GEMINI|ENABLE_CODEX|ENABLE_MISTRAL|ENABLE_CURSOR|ENABLE_KIMI|ENABLE_CLAUDE|ENABLE_QWEN3|ENABLE_GLM|ENABLE_GROK|ENABLE_DEEPSEEK|ENABLE_MINIMAX|GEMINI_USE_API|CODEX_USE_API|MISTRAL_USE_API|CLAUDE_USE_API|QWEN3_USE_API|MINIMAX_USE_API|GEMINI_API_KEY|OPENAI_API_KEY|MISTRAL_API_KEY|ANTHROPIC_API_KEY|QWEN3_API_KEY|MINIMAX_API_KEY|GLM_API_KEY|GROK_API_KEY|DEEPSEEK_API_KEY) continue ;;
|
|
405
|
+
ENABLE_GEMINI|ENABLE_CODEX|ENABLE_MISTRAL|ENABLE_CURSOR|ENABLE_KIMI|ENABLE_CLAUDE|ENABLE_QWEN3|ENABLE_GLM|ENABLE_GROK|ENABLE_DEEPSEEK|ENABLE_MINIMAX|GEMINI_USE_API|CODEX_USE_API|MISTRAL_USE_API|CLAUDE_USE_API|QWEN3_USE_API|GROK_USE_API|MINIMAX_USE_API|GEMINI_API_KEY|OPENAI_API_KEY|MISTRAL_API_KEY|ANTHROPIC_API_KEY|QWEN3_API_KEY|MINIMAX_API_KEY|GLM_API_KEY|GROK_API_KEY|DEEPSEEK_API_KEY) continue ;;
|
|
363
406
|
esac
|
|
364
407
|
prompt_value "$key"
|
|
365
408
|
done 3< <(list_parameters)
|
|
@@ -368,7 +411,11 @@ fi
|
|
|
368
411
|
|
|
369
412
|
# Explicit command-line overrides have final precedence.
|
|
370
413
|
for ((i=0; i<${#SET_KEYS[@]}; i++)); do
|
|
371
|
-
|
|
414
|
+
if [[ "${SET_KEYS[$i]}" == *_MODEL ]]; then
|
|
415
|
+
set_value "${SET_KEYS[$i]}" "${SET_VALUES[$i]} $PIN_MARKER"
|
|
416
|
+
else
|
|
417
|
+
set_value "${SET_KEYS[$i]}" "${SET_VALUES[$i]}"
|
|
418
|
+
fi
|
|
372
419
|
done
|
|
373
420
|
|
|
374
421
|
enabled_count=0
|
package/scripts/doctor.sh
CHANGED
|
@@ -219,10 +219,9 @@ check_cli_consultant() {
|
|
|
219
219
|
return 0
|
|
220
220
|
fi
|
|
221
221
|
|
|
222
|
-
#
|
|
223
|
-
#
|
|
224
|
-
#
|
|
225
|
-
# by check_api_mode. This matters most for Gemini, which auto-resolves to
|
|
222
|
+
# Switchable agents skip the CLI requirement while explicitly in API mode;
|
|
223
|
+
# the API key is validated separately by check_api_mode. This matters most
|
|
224
|
+
# for Gemini, which auto-resolves to
|
|
226
225
|
# API mode whenever GEMINI_API_KEY is set (the npm-friendly path).
|
|
227
226
|
local use_api_var="${env_var}_USE_API"
|
|
228
227
|
if [[ "${!use_api_var:-false}" == "true" ]]; then
|
|
@@ -238,7 +237,9 @@ check_cli_consultant() {
|
|
|
238
237
|
fi
|
|
239
238
|
add_issue "consultant" "$name CLI not found" "$install_cmd"
|
|
240
239
|
check_fail
|
|
241
|
-
|
|
240
|
+
# A failed health check is data for the final diagnosis, not a reason
|
|
241
|
+
# to abort the diagnostic pipeline under `set -e`.
|
|
242
|
+
return 0
|
|
242
243
|
fi
|
|
243
244
|
|
|
244
245
|
# Get version (--version is standard and fast, no timeout needed)
|
|
@@ -265,6 +266,7 @@ check_cli_consultants() {
|
|
|
265
266
|
check_cli_consultant "Kimi" "$KIMI_CMD" "curl -L code.kimi.com/install.sh | bash" "KIMI"
|
|
266
267
|
check_cli_consultant "Claude" "$CLAUDE_CMD" "See https://docs.anthropic.com/claude-code" "CLAUDE"
|
|
267
268
|
check_cli_consultant "Qwen" "$QWEN3_CMD" "npm install -g @qwen-code/qwen-code@latest" "QWEN3"
|
|
269
|
+
check_cli_consultant "Grok Build" "$GROK_CMD" "curl -fsSL https://x.ai/cli/install.sh | bash" "GROK"
|
|
268
270
|
check_cli_consultant "MiniMax" "$MINIMAX_CMD" "npm install -g mmx-cli" "MINIMAX"
|
|
269
271
|
}
|
|
270
272
|
|
|
@@ -291,7 +293,7 @@ check_api_mode() {
|
|
|
291
293
|
_print " ✗ $name: API mode enabled but $api_key_var not set"
|
|
292
294
|
add_issue "api_mode" "$name API mode enabled but API key missing" "export ${api_key_var}='your-api-key'"
|
|
293
295
|
check_fail
|
|
294
|
-
return
|
|
296
|
+
return 0
|
|
295
297
|
else
|
|
296
298
|
local masked_key="${api_key:0:4}...${api_key: -4}"
|
|
297
299
|
_print " ✓ $name: API mode (key: $masked_key)"
|
|
@@ -308,7 +310,7 @@ check_api_mode_switching() {
|
|
|
308
310
|
local has_api_mode=false
|
|
309
311
|
|
|
310
312
|
# Check switchable consultants
|
|
311
|
-
for agent in GEMINI CODEX CLAUDE MISTRAL QWEN3 MINIMAX; do
|
|
313
|
+
for agent in GEMINI CODEX CLAUDE MISTRAL QWEN3 GROK MINIMAX; do
|
|
312
314
|
local enabled_var="ENABLE_${agent}"
|
|
313
315
|
local use_api_var="${agent}_USE_API"
|
|
314
316
|
local is_enabled="${!enabled_var:-false}"
|
|
@@ -326,6 +328,7 @@ check_api_mode_switching() {
|
|
|
326
328
|
check_api_mode "Claude" "CLAUDE_USE_API" "ANTHROPIC_API_KEY" "ENABLE_CLAUDE"
|
|
327
329
|
check_api_mode "Mistral" "MISTRAL_USE_API" "MISTRAL_API_KEY" "ENABLE_MISTRAL"
|
|
328
330
|
check_api_mode "Qwen3" "QWEN3_USE_API" "QWEN3_API_KEY" "ENABLE_QWEN3"
|
|
331
|
+
check_api_mode "Grok" "GROK_USE_API" "GROK_API_KEY" "ENABLE_GROK"
|
|
329
332
|
check_api_mode "MiniMax" "MINIMAX_USE_API" "MINIMAX_API_KEY" "ENABLE_MINIMAX"
|
|
330
333
|
else
|
|
331
334
|
_print " ○ All switchable consultants using CLI mode"
|
|
@@ -357,7 +360,7 @@ check_api_consultant() {
|
|
|
357
360
|
_print " ✗ $name: API key not set"
|
|
358
361
|
add_issue "api" "$name API key not configured" "export ${api_key_var}='your-api-key'"
|
|
359
362
|
check_fail
|
|
360
|
-
return
|
|
363
|
+
return 0
|
|
361
364
|
fi
|
|
362
365
|
|
|
363
366
|
# Mask API key for display
|
|
@@ -383,7 +386,6 @@ check_api_consultants() {
|
|
|
383
386
|
print_section "Checking API-only Consultants"
|
|
384
387
|
|
|
385
388
|
check_api_consultant "GLM" "GLM_API_KEY" "GLM_API_URL" "ENABLE_GLM"
|
|
386
|
-
check_api_consultant "Grok" "GROK_API_KEY" "GROK_API_URL" "ENABLE_GROK"
|
|
387
389
|
check_api_consultant "DeepSeek" "DEEPSEEK_API_KEY" "DEEPSEEK_API_URL" "ENABLE_DEEPSEEK"
|
|
388
390
|
}
|
|
389
391
|
|
|
@@ -773,6 +775,7 @@ suggest_configuration() {
|
|
|
773
775
|
"ENABLE_KIMI:${KIMI_CMD:-kimi}"
|
|
774
776
|
"ENABLE_CLAUDE:${CLAUDE_CMD:-claude}"
|
|
775
777
|
"ENABLE_QWEN3:${QWEN3_CMD:-qwen}"
|
|
778
|
+
"ENABLE_GROK:${GROK_CMD:-grok}"
|
|
776
779
|
"ENABLE_MINIMAX:${MINIMAX_CMD:-mmx}"
|
|
777
780
|
)
|
|
778
781
|
|
|
@@ -781,7 +784,8 @@ suggest_configuration() {
|
|
|
781
784
|
for entry in "${consultant_clis[@]}"; do
|
|
782
785
|
local flag="${entry%%:*}"
|
|
783
786
|
local cmd="${entry##*:}"
|
|
784
|
-
if command -v "$cmd" >/dev/null 2>&1
|
|
787
|
+
if command -v "$cmd" >/dev/null 2>&1 || \
|
|
788
|
+
[[ "$flag" == "ENABLE_GROK" && -n "${GROK_API_KEY:-}" ]]; then
|
|
785
789
|
lines+=("${flag}=true")
|
|
786
790
|
((available_count++)) || true
|
|
787
791
|
else
|
|
@@ -792,7 +796,6 @@ suggest_configuration() {
|
|
|
792
796
|
# API-only consultants: enable if API key is set
|
|
793
797
|
local api_consultants=(
|
|
794
798
|
"ENABLE_GLM:GLM_API_KEY"
|
|
795
|
-
"ENABLE_GROK:GROK_API_KEY"
|
|
796
799
|
"ENABLE_DEEPSEEK:DEEPSEEK_API_KEY"
|
|
797
800
|
)
|
|
798
801
|
for entry in "${api_consultants[@]}"; do
|
|
@@ -856,13 +859,15 @@ _count_available_consultants() {
|
|
|
856
859
|
"KIMI|ENABLE_KIMI|${KIMI_CMD:-kimi}"
|
|
857
860
|
"CLAUDE|ENABLE_CLAUDE|${CLAUDE_CMD:-claude}"
|
|
858
861
|
"QWEN3|ENABLE_QWEN3|${QWEN3_CMD:-qwen}"
|
|
862
|
+
"GROK|ENABLE_GROK|${GROK_CMD:-grok}"
|
|
859
863
|
"MINIMAX|ENABLE_MINIMAX|${MINIMAX_CMD:-mmx}"
|
|
860
864
|
)
|
|
861
865
|
for entry in "${entries[@]}"; do
|
|
862
866
|
IFS='|' read -r name flag cmd <<<"$entry"
|
|
863
867
|
local enabled="${!flag:-false}"
|
|
864
868
|
[[ "$enabled" != "true" ]] && continue
|
|
865
|
-
if command -v "$cmd" >/dev/null 2>&1
|
|
869
|
+
if command -v "$cmd" >/dev/null 2>&1 || \
|
|
870
|
+
[[ "$name" == "GROK" && -n "${GROK_API_KEY:-}" ]]; then
|
|
866
871
|
[[ "$name" == "$invoker_consultant" ]] && continue
|
|
867
872
|
((count++)) || true
|
|
868
873
|
fi
|
|
@@ -871,7 +876,6 @@ _count_available_consultants() {
|
|
|
871
876
|
# API-only consultants: enabled flag + API key both required
|
|
872
877
|
local api_entries=(
|
|
873
878
|
"GLM|ENABLE_GLM|GLM_API_KEY"
|
|
874
|
-
"GROK|ENABLE_GROK|GROK_API_KEY"
|
|
875
879
|
"DEEPSEEK|ENABLE_DEEPSEEK|DEEPSEEK_API_KEY"
|
|
876
880
|
)
|
|
877
881
|
for entry in "${api_entries[@]}"; do
|
package/scripts/lib/api.sh
CHANGED
|
@@ -249,7 +249,7 @@ build_openai_request() {
|
|
|
249
249
|
build_anthropic_request() {
|
|
250
250
|
local prompt="$1"
|
|
251
251
|
local model="${2:-claude-sonnet-4-6}"
|
|
252
|
-
local max_tokens="${3:-
|
|
252
|
+
local max_tokens="${3:-16384}"
|
|
253
253
|
|
|
254
254
|
jq -n \
|
|
255
255
|
--arg model "$model" \
|
|
@@ -327,7 +327,11 @@ parse_anthropic_response() {
|
|
|
327
327
|
local response="$1"
|
|
328
328
|
|
|
329
329
|
local content
|
|
330
|
-
|
|
330
|
+
# Opus 5 may put a thinking block before the visible text block. Select
|
|
331
|
+
# every text block instead of assuming content[0] is user-visible output.
|
|
332
|
+
content=$(echo "$response" | jq -r \
|
|
333
|
+
'[.content[]? | select(.type == "text") | (.text // "")] | join("\n")' \
|
|
334
|
+
2>/dev/null)
|
|
331
335
|
|
|
332
336
|
if [[ -n "$content" && "$content" != "null" ]]; then
|
|
333
337
|
echo "$content"
|
package/scripts/lib/api_query.sh
CHANGED
|
@@ -94,7 +94,14 @@ run_api_mode_query() {
|
|
|
94
94
|
if [[ -n "$effort" ]]; then
|
|
95
95
|
log_warn "[$consultant_name] $effort_var is not supported on the 'anthropic' wire format and is ignored."
|
|
96
96
|
fi
|
|
97
|
-
|
|
97
|
+
local max_tokens_var api_max_tokens
|
|
98
|
+
max_tokens_var="$(to_upper "$consultant_name")_API_MAX_TOKENS"
|
|
99
|
+
api_max_tokens="${!max_tokens_var:-16384}"
|
|
100
|
+
if ! [[ "$api_max_tokens" =~ ^[1-9][0-9]*$ ]]; then
|
|
101
|
+
log_error "[$consultant_name] $max_tokens_var must be a positive integer (got: $api_max_tokens)"
|
|
102
|
+
return 1
|
|
103
|
+
fi
|
|
104
|
+
request_body=$(build_anthropic_request "$query" "$model" "$api_max_tokens")
|
|
98
105
|
auth_style="anthropic"
|
|
99
106
|
;;
|
|
100
107
|
qwen)
|
|
@@ -134,6 +141,16 @@ run_api_mode_query() {
|
|
|
134
141
|
local raw_response
|
|
135
142
|
raw_response=$(cat "$temp_response")
|
|
136
143
|
|
|
144
|
+
# Anthropic counts adaptive thinking and visible output against the same
|
|
145
|
+
# max_tokens budget. A max_tokens stop is therefore an incomplete answer,
|
|
146
|
+
# not a successful partial response suitable for synthesis.
|
|
147
|
+
if [[ "$api_format" == "anthropic" ]] \
|
|
148
|
+
&& [[ "$(jq -r '.stop_reason // empty' <<<"$raw_response" 2>/dev/null)" == "max_tokens" ]]; then
|
|
149
|
+
log_error "[$consultant_name] API response was truncated at ${api_max_tokens:-the configured} max tokens"
|
|
150
|
+
rm -f "$temp_response"
|
|
151
|
+
return 1
|
|
152
|
+
fi
|
|
153
|
+
|
|
137
154
|
local parsed_content
|
|
138
155
|
case "$api_format" in
|
|
139
156
|
google_ai)
|