ai-consultants 3.2.0 → 3.3.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/CLAUDE.md CHANGED
@@ -6,7 +6,7 @@ AI Consultants is a multi-model coverage system that queries up to 11 AI consult
6
6
 
7
7
  **Self-Exclusion**: The invoking agent is automatically excluded from the panel to prevent self-consultation. Claude Code won't query Claude, Codex CLI won't query Codex, etc.
8
8
 
9
- **Version**: 3.2.0
9
+ **Version**: 3.3.0
10
10
 
11
11
  ## Distribution
12
12
 
@@ -787,6 +787,12 @@ curl -fsSL https://raw.githubusercontent.com/matteoscurati/ai-consultants/main/s
787
787
 
788
788
  ## Changelog
789
789
 
790
+ ### v3.3.0
791
+ - **Grok and Kimi compatibility is now established from capabilities, not inferred from an installed binary or its version string.** `grok_cli_supports_required_interface` validates the complete headless parser surface inside the same isolated HOME/CWD boundary used for dispatch, while `grok_cli_exposes_requested_model` verifies both usable authentication and the exact `GROK_MODEL` in the CLI inventory (`scripts/query_grok.sh:85-154`). Kimi similarly checks prompt mode, `stream-json`, the provider inventory, and `KIMI_MODEL` before any request (`scripts/query_kimi.sh:45-79`). Compatible future and vendor-custom versions therefore continue to work without a release-specific allowlist; an interface that cannot enforce the adapter's contract fails before a model call.
792
+ - **The observed CLI version is provenance only.** Successful Grok and Kimi responses add `metadata.cli_version` and `metadata.cli_compatibility="capability-probed"`; the shared schema documents both fields without making either required for other transports (`scripts/query_grok.sh:319-336`, `scripts/query_kimi.sh:126-138`, `scripts/lib/schema.json:169-180`). This deliberately does not introduce a blessed-version range: the version is useful for diagnosis, while compatibility is decided by the exercised command, output, and model surfaces.
793
+ - **Optional capabilities remain optional.** Grok's `--no-auto-update` is used when the help surface advertises it, but its absence does not reject an otherwise compatible CLI. The capability probe itself uses `--help` and model/provider inventory commands; it does not send a consultation. Grok preserves its existing narrowly classified API fallback when the required CLI route is unavailable, while Kimi continues to fail closed because it has no API transport.
794
+ - **Regression coverage pins the compatibility contract rather than today's binaries.** Grok's suite accepts an alternate compatible version, rejects an incomplete interface before dispatch, checks requested-model availability, and preserves the post-launch/API-fallback boundary (32 checks). Kimi's suite covers an alternate compatible version, an incomplete interface, and a missing requested model (8 checks). Full release gate: 17/17 suites; core suite: 299/299; ShellCheck green. Installed Grok 0.2.114 and Kimi 0.27.0 also passed no-model-call probes.
795
+
790
796
  ### v3.2.0
791
797
  - **Claude premium upgraded from Opus 4.8 to Opus 5.** The default `CLAUDE_MODEL`, premium/max/best tier, standalone adapter fallback, configuration examples, model table, and cost catalog now resolve to the canonical `claude-opus-5` ID (`scripts/config.sh:274`, `scripts/query_claude.sh:29`). Pricing remains $5/$25 per million tokens; `claude-opus-4-8` stays in the legacy catalog for historical responses and intentional pins.
792
798
  - **Opus 5 adaptive thinking is accounted for end to end.** Claude CLI mode now requests the JSON result envelope, extracts visible `.result`, aggregates provider usage across `modelUsage`, and persists the provider's exact `costUSD` (`scripts/query_claude.sh:72-126`, `scripts/lib/common.sh:904-980`, `scripts/lib/costs.sh:307-354`). This fixes the review finding that pricing only the visible answer undercounted hidden thinking and cache charges. The implementation deliberately prefers provider cost over reconstructing cache pricing from token totals.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
- # AI Consultants v3.2.0
1
+ # AI Consultants v3.3.0
2
2
 
3
3
  > **Coverage, not a single guess.** A panel of up to 11 frontier models from different vendors fans out on your question in parallel and hands you the *union* of what they collectively see — the risks, edge cases, and approaches a single model misses.
4
4
 
5
- [![Version](https://img.shields.io/badge/version-3.2.0-blue.svg)](https://github.com/matteoscurati/ai-consultants)
5
+ [![Version](https://img.shields.io/badge/version-3.3.0-blue.svg)](https://github.com/matteoscurati/ai-consultants)
6
6
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7
7
  [![Claude Code Skill](https://img.shields.io/badge/Claude%20Code-Skill-orange.svg)](https://docs.anthropic.com/en/docs/claude-code/skills)
8
8
  [![GitHub stars](https://img.shields.io/github/stars/matteoscurati/ai-consultants?style=social)](https://github.com/matteoscurati/ai-consultants)
@@ -388,7 +388,10 @@ to the xAI API only when the CLI is missing, cannot launch, or has no usable
388
388
  authentication and `GROK_API_KEY` is configured; post-launch request failures
389
389
  are surfaced without a silent API charge. Qwen3 and MiniMax can also switch
390
390
  from their CLI to API transport. Gemini, Codex, Claude, and Mistral are
391
- CLI/API switchable.
391
+ CLI/API switchable. Grok and Kimi compatibility is capability-probed before
392
+ dispatch: the requested model, headless arguments, and structured-output
393
+ surface must be available. Any CLI version is accepted when those checks pass;
394
+ the observed version is response provenance only.
392
395
 
393
396
  ### API-Only Consultants
394
397
 
package/SKILL.md CHANGED
@@ -5,10 +5,10 @@ license: MIT
5
5
  compatibility: Requires bash, jq, and at least 2 AI CLI tools (agy, codex, vibe, etc.). macOS and Linux.
6
6
  metadata:
7
7
  author: matteoscurati
8
- version: 3.2.0
8
+ version: 3.3.0
9
9
  ---
10
10
 
11
- # AI Consultants v3.2.0 - AI Expert Panel
11
+ # AI Consultants v3.3.0 - AI Expert Panel
12
12
 
13
13
  **Coverage, not a single guess.** Convene a panel of AI "consultants" from different vendors for coding questions: they fan out in parallel and you get the *union* of what they collectively see — the risks, edge cases, and approaches a single model misses. Each consultant has a **configurable persona** that decorrelates its analysis.
14
14
 
@@ -45,6 +45,11 @@ Configuration (presets, strategies, features, personas, API keys) can be managed
45
45
 
46
46
  **CLI/API Mode**: Gemini, Codex, Claude, Mistral, Qwen, Grok, and MiniMax can switch between CLI and API mode via `*_USE_API` environment variables. Grok is CLI-first on Grok Build with `grok-4.5` and falls back to the xAI API when the CLI cannot run. Gemini auto-selects API mode when `GEMINI_API_KEY` is set (no `agy` install needed) and the CLI otherwise.
47
47
 
48
+ Grok and Kimi are compatible by capability rather than by CLI version. Before
49
+ dispatch, their adapters verify the required headless arguments, requested
50
+ model, and structured-output surface. Compatible version changes are accepted;
51
+ the observed version is recorded only as response provenance.
52
+
48
53
  **Self-Exclusion**: The invoking agent is automatically excluded from the panel. When invoked from Claude Code, Claude is excluded; when invoked from Codex CLI, Codex is excluded, etc.
49
54
 
50
55
  ## Requirements
@@ -1,4 +1,4 @@
1
- # Cost Rates - AI Consultants v3.2.0
1
+ # Cost Rates - AI Consultants v3.3.0
2
2
 
3
3
  This page documents the per-token rates used by the cost tracking system.
4
4
 
@@ -37,6 +37,8 @@ The schema is defined in `scripts/lib/schema.json` following JSON Schema Draft-0
37
37
  "tokens_output": 300,
38
38
  "latency_ms": 2345,
39
39
  "model_version": "gemini-3.1-pro-preview",
40
+ "cli_version": "0.27.0",
41
+ "cli_compatibility": "capability-probed",
40
42
  "timestamp": "2024-01-14T12:34:56Z"
41
43
  }
42
44
  }
@@ -209,6 +211,8 @@ Present only if Multi-Agent Debate is enabled (round >= 2):
209
211
  | `tokens_output` | integer | Completion tokens, when the provider reported them (API mode only) |
210
212
  | `latency_ms` | integer | Response time in ms |
211
213
  | `model_version` | string | Exact model version |
214
+ | `cli_version` | string | Observed CLI version for provenance; never a compatibility gate |
215
+ | `cli_compatibility` | string | Capability-probe result: `capability-probed` or `incompatible` |
212
216
  | `timestamp` | string | ISO 8601 timestamp |
213
217
 
214
218
  ## Enum Values
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "3.2.0",
2
+ "version": "3.3.0",
3
3
  "updated": "2026-07-25",
4
4
  "models": {
5
5
  "_comment_units": "All rates are USD per 1,000 tokens (per-1K). lib/costs.sh computes cost as (token_count / 1000) * rate, so every value here MUST be a per-1K rate = (provider $/1M price) / 1000. Do NOT paste $/MTok figures directly.",
@@ -0,0 +1,80 @@
1
+ # Release v3.3.0
2
+
3
+ **Date:** 2026-07-29
4
+ **Type:** Minor — capability-based Grok and Kimi CLI compatibility
5
+ **Previous:** v3.2.0
6
+
7
+ ## Highlights
8
+
9
+ - Grok and Kimi now prove CLI compatibility from the interface they actually need, not from a version string.
10
+ - Compatible future and vendor-custom CLI versions are accepted without a release-specific allowlist.
11
+ - Incomplete interfaces and missing requested models are rejected before a model request begins.
12
+ - Responses expose the observed CLI version as provenance alongside the capability-probe result.
13
+
14
+ ## What's New
15
+
16
+ ### Capability-based CLI compatibility
17
+
18
+ Before dispatch, the Grok adapter validates its complete headless argument
19
+ surface, strict sandbox controls, structured output, authentication state, and
20
+ the requested model. The probe runs inside an isolated environment and does not
21
+ send a consultation.
22
+
23
+ Kimi now validates prompt mode, `stream-json`, provider inventory, and the exact
24
+ configured model before dispatch. A CLI with a different version number remains
25
+ compatible when these capabilities are present; a CLI that cannot satisfy the
26
+ contract fails before a model call.
27
+
28
+ Grok's `--no-auto-update` flag remains optional. It is enabled when the installed
29
+ CLI advertises it and omitted otherwise, so a useful automation control does not
30
+ become an accidental version constraint.
31
+
32
+ ### Diagnostic provenance
33
+
34
+ Successful Grok and Kimi CLI responses now include:
35
+
36
+ | Field | Meaning |
37
+ |---|---|
38
+ | `metadata.cli_version` | The version reported by the CLI, retained for diagnosis and provenance |
39
+ | `metadata.cli_compatibility` | `capability-probed` when the required interface passed |
40
+
41
+ These fields are additive. Existing response consumers and non-CLI transports
42
+ do not need to provide them.
43
+
44
+ ### Verification
45
+
46
+ - Full repository gate: 17/17 suites
47
+ - Core suite: 299/299 checks
48
+ - Grok adapter suite: 32/32 checks
49
+ - Kimi adapter suite: 8/8 checks
50
+ - ShellCheck: green
51
+ - Installed Grok 0.2.114 and Kimi 0.27.0: no-model-call capability probes passed
52
+
53
+ ## Breaking Changes
54
+
55
+ None — this release is backwards-compatible. No configuration changes are
56
+ required.
57
+
58
+ An installed Grok or Kimi CLI that lacks the adapter's required command,
59
+ structured-output, or requested-model surface will now be rejected before
60
+ dispatch instead of failing later during a consultation.
61
+
62
+ ## Upgrade Guide
63
+
64
+ ```bash
65
+ # npx (no install)
66
+ npx ai-consultants@latest "your question"
67
+
68
+ # git clone install
69
+ cd ~/.claude/skills/ai-consultants && git pull
70
+
71
+ # curl | bash install
72
+ curl -fsSL https://raw.githubusercontent.com/matteoscurati/ai-consultants/main/scripts/install.sh | bash
73
+ ```
74
+
75
+ No configuration changes are required. If an adapter reports an incompatible
76
+ CLI, update that CLI and run `ai-consultants doctor` before retrying.
77
+
78
+ ## Commits
79
+
80
+ - `c7bad95` Harden CLI capability checks
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-consultants",
3
- "version": "3.2.0",
3
+ "version": "3.3.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"
@@ -263,10 +263,15 @@ tool-free strict sandbox. If the CLI is missing, cannot execute, or has no
263
263
  usable authentication, the same query and model fall back to `GROK_API_URL`
264
264
  when `GROK_API_KEY` is set. Failures after a request launches (including
265
265
  timeouts, model errors, and empty output) are returned without API fallback.
266
- Set `GROK_USE_API=true` only to force the API path.
266
+ Set `GROK_USE_API=true` only to force the API path. The adapter accepts any CLI
267
+ version that exposes the complete required headless interface and requested
268
+ model; `metadata.cli_version` is provenance, not a version pin.
267
269
 
268
270
  `KIMI_MODEL` is passed directly to `kimi --model`, so `kimi-code/k3` overrides
269
- any older default stored in the user's Kimi CLI configuration.
271
+ any older default stored in the user's Kimi CLI configuration. Kimi CLI
272
+ compatibility is also capability-probed: prompt mode, `stream-json`, provider
273
+ inventory, and the requested model must be present. No numeric CLI version is
274
+ used as a gate.
270
275
 
271
276
  ## Model Quality Tiers (v2.5)
272
277
 
package/scripts/config.sh CHANGED
@@ -779,4 +779,4 @@ EOF
779
779
  # VERSION
780
780
  # =============================================================================
781
781
 
782
- AI_CONSULTANTS_VERSION="3.2.0"
782
+ AI_CONSULTANTS_VERSION="3.3.0"
@@ -167,6 +167,15 @@
167
167
  "type": "string",
168
168
  "description": "Exact model version string"
169
169
  },
170
+ "cli_version": {
171
+ "type": "string",
172
+ "description": "Observed consultant CLI version for provenance only; compatibility is not decided from this string."
173
+ },
174
+ "cli_compatibility": {
175
+ "type": "string",
176
+ "enum": ["capability-probed", "incompatible"],
177
+ "description": "Result of checking the CLI's required command, model, and structured-output capabilities before dispatch."
178
+ },
170
179
  "timestamp": {
171
180
  "type": "string",
172
181
  "format": "date-time",
@@ -36,6 +36,9 @@ START_TIME=$(get_timestamp_ms)
36
36
  TEMP_OUTPUT=$(mktemp)
37
37
  GROK_RUNTIME_DIR=""
38
38
  TRANSPORT="cli"
39
+ GROK_CLI_VERSION=""
40
+ GROK_CLI_COMPATIBILITY=""
41
+ GROK_SUPPORTS_NO_AUTO_UPDATE=false
39
42
  exit_code=1
40
43
 
41
44
  cleanup() {
@@ -67,6 +70,93 @@ run_grok_api() {
67
70
  fi
68
71
  }
69
72
 
73
+ observe_grok_cli_version() {
74
+ local version
75
+ version=$("$GROK_CMD" --version 2>/dev/null | head -1 || true)
76
+ if [[ "$version" =~ ^grok[[:space:]]+([^[:space:]]+) ]]; then
77
+ printf '%s\n' "${BASH_REMATCH[1]}"
78
+ elif [[ -n "$version" ]]; then
79
+ printf '%s\n' "$version"
80
+ else
81
+ printf 'unknown\n'
82
+ fi
83
+ }
84
+
85
+ grok_cli_supports_required_interface() {
86
+ local probe_home="$1"
87
+ local probe_grok_home="$2"
88
+ local probe_workspace="$3"
89
+ local help flag
90
+
91
+ help=$(env HOME="$probe_home" GROK_HOME="$probe_grok_home" \
92
+ "$GROK_CMD" --help 2>&1 || true)
93
+ for flag in \
94
+ --prompt-file --model --cwd --output-format --no-plan --no-subagents \
95
+ --no-memory --disable-web-search --max-turns --permission-mode \
96
+ --sandbox --tools --deny --verbatim; do
97
+ grep -q -- "$flag" <<< "$help" || return 1
98
+ done
99
+ grep -Eq '^[[:space:]]+models([[:space:]]|$)' <<< "$help" || return 1
100
+
101
+ # Exercise the complete headless argument surface under --help. This checks
102
+ # parser compatibility without starting a session or sending a prompt.
103
+ env HOME="$probe_home" GROK_HOME="$probe_grok_home" \
104
+ "$GROK_CMD" \
105
+ --prompt-file /dev/null \
106
+ -m "$GROK_MODEL" \
107
+ --cwd "$probe_workspace" \
108
+ --output-format plain \
109
+ --no-plan \
110
+ --no-subagents \
111
+ --no-memory \
112
+ --disable-web-search \
113
+ --max-turns 1 \
114
+ --permission-mode dontAsk \
115
+ --sandbox strict \
116
+ --tools "" \
117
+ --deny Bash \
118
+ --deny Edit \
119
+ --deny Read \
120
+ --deny Grep \
121
+ --deny MCPTool \
122
+ --deny WebFetch \
123
+ --deny WebSearch \
124
+ --verbatim \
125
+ --help >/dev/null 2>&1 || return 1
126
+
127
+ if grep -q -- '--no-auto-update' <<< "$help"; then
128
+ GROK_SUPPORTS_NO_AUTO_UPDATE=true
129
+ else
130
+ GROK_SUPPORTS_NO_AUTO_UPDATE=false
131
+ fi
132
+ GROK_CLI_COMPATIBILITY="capability-probed"
133
+ }
134
+
135
+ grok_cli_exposes_requested_model() {
136
+ local isolated_home="$1"
137
+ local isolated_grok_home="$2"
138
+ local models
139
+
140
+ if ! models=$(env HOME="$isolated_home" GROK_HOME="$isolated_grok_home" \
141
+ "$GROK_CMD" models 2>&1); then
142
+ printf '%s\n' "$models"
143
+ return 1
144
+ fi
145
+ grep -Fq "You are logged in with grok.com." <<< "$models" || {
146
+ printf '%s\n' "$models"
147
+ return 1
148
+ }
149
+ awk -v requested="$GROK_MODEL" '
150
+ {
151
+ line = $0
152
+ sub(/^[[:space:]*]+/, "", line)
153
+ split(line, fields, /[[:space:]]+/)
154
+ if (fields[1] == requested) found = 1
155
+ }
156
+ END { exit(found ? 0 : 1) }
157
+ ' <<< "$models"
158
+ }
159
+
70
160
  grok_cli_is_unavailable() {
71
161
  local cli_exit_code="$1"
72
162
  local error_file="$2"
@@ -85,7 +175,7 @@ grok_cli_is_unavailable() {
85
175
  # model errors, timeouts, empty output, or other post-launch failures here;
86
176
  # those must surface instead of silently creating a billable API request.
87
177
  grep -Eiq \
88
- 'not authenticated|authentication( is)? required|authentication failed|unauthorized|run .?grok login|please .*log ?in|no (valid )?(credentials|access token)|missing .*credential|token.*expired|(^|[^0-9])401([^0-9]|$)|permission denied|cannot execute|exec format error|no such file or directory|failed to (start|launch|spawn)|could not (start|launch|spawn)' \
178
+ 'not authenticated|authentication( is)? required|authentication failed|unauthorized|run .?grok login|please .*log ?in|no (valid )?(credentials|access token)|missing .*credential|token.*expired|(^|[^0-9])401([^0-9]|$)|permission denied|cannot execute|exec format error|no such file or directory|failed to (start|launch|spawn)|could not (start|launch|spawn)|lacks the required capabilities|does not expose the requested model' \
89
179
  "$error_file"
90
180
  }
91
181
 
@@ -128,51 +218,66 @@ else
128
218
  fi
129
219
  fi
130
220
 
131
- # Official Grok Build headless contract:
132
- # --prompt-file avoids argv size/process-list exposure, -m pins the
133
- # model, and plain output contains the final assistant text.
134
- # dontAsk + strict sandbox make every unapproved tool fail closed.
135
- GROK_ARGS=(
136
- env
137
- HOME="$isolated_home"
138
- GROK_HOME="$isolated_grok_home"
139
- "$GROK_CMD"
140
- --prompt-file "$prompt_file"
141
- -m "$GROK_MODEL"
142
- --cwd "$isolated_workspace"
143
- --output-format plain
144
- --no-plan
145
- --no-subagents
146
- --no-memory
147
- --disable-web-search
148
- --max-turns 1
149
- --permission-mode dontAsk
150
- --sandbox strict
151
- --tools ""
152
- --deny Bash
153
- --deny Edit
154
- --deny Read
155
- --deny Grep
156
- --deny MCPTool
157
- --deny WebFetch
158
- --deny WebSearch
159
- --verbatim
160
- )
161
-
162
- # Newer Grok Build releases document --no-auto-update for automation;
163
- # keep compatibility with older installed builds that do not expose it.
164
- if "$GROK_CMD" --help 2>&1 | grep -q -- '--no-auto-update'; then
165
- GROK_ARGS+=("--no-auto-update")
166
- fi
167
-
168
- if run_query \
169
- "$CONSULTANT_NAME" \
170
- "$TEMP_OUTPUT" \
171
- "$GROK_TIMEOUT_SECONDS" \
172
- "${GROK_ARGS[@]}" </dev/null; then
173
- exit_code=0
221
+ GROK_CLI_VERSION=$(observe_grok_cli_version)
222
+ if ! grok_cli_supports_required_interface \
223
+ "$isolated_home" "$isolated_grok_home" "$isolated_workspace"; then
224
+ GROK_CLI_COMPATIBILITY="incompatible"
225
+ printf 'Grok Build CLI lacks the required capabilities\n' > "${TEMP_OUTPUT}.err"
226
+ log_warn "[$CONSULTANT_NAME] Grok Build CLI is capability-incompatible (reported version: $GROK_CLI_VERSION)"
227
+ exit_code=69
228
+ elif ! grok_cli_exposes_requested_model \
229
+ "$isolated_home" "$isolated_grok_home" > "${TEMP_OUTPUT}.err"; then
230
+ printf 'Grok Build CLI does not expose the requested model %s\n' \
231
+ "$GROK_MODEL" >> "${TEMP_OUTPUT}.err"
232
+ log_warn "[$CONSULTANT_NAME] Grok Build CLI does not expose $GROK_MODEL"
233
+ exit_code=69
174
234
  else
175
- exit_code=$?
235
+ # Official Grok Build headless contract:
236
+ # --prompt-file avoids argv size/process-list exposure, -m pins the
237
+ # model, and plain output contains the final assistant text.
238
+ # dontAsk + strict sandbox make every unapproved tool fail closed.
239
+ GROK_ARGS=(
240
+ env
241
+ HOME="$isolated_home"
242
+ GROK_HOME="$isolated_grok_home"
243
+ "$GROK_CMD"
244
+ --prompt-file "$prompt_file"
245
+ -m "$GROK_MODEL"
246
+ --cwd "$isolated_workspace"
247
+ --output-format plain
248
+ --no-plan
249
+ --no-subagents
250
+ --no-memory
251
+ --disable-web-search
252
+ --max-turns 1
253
+ --permission-mode dontAsk
254
+ --sandbox strict
255
+ --tools ""
256
+ --deny Bash
257
+ --deny Edit
258
+ --deny Read
259
+ --deny Grep
260
+ --deny MCPTool
261
+ --deny WebFetch
262
+ --deny WebSearch
263
+ --verbatim
264
+ )
265
+
266
+ # --no-auto-update is a useful optional capability, not a version
267
+ # requirement. Compatible older or vendor-custom builds may omit it.
268
+ if [[ "$GROK_SUPPORTS_NO_AUTO_UPDATE" == "true" ]]; then
269
+ GROK_ARGS+=("--no-auto-update")
270
+ fi
271
+
272
+ if run_query \
273
+ "$CONSULTANT_NAME" \
274
+ "$TEMP_OUTPUT" \
275
+ "$GROK_TIMEOUT_SECONDS" \
276
+ "${GROK_ARGS[@]}" </dev/null; then
277
+ exit_code=0
278
+ else
279
+ exit_code=$?
280
+ fi
176
281
  fi
177
282
  else
178
283
  log_warn "[$CONSULTANT_NAME] Grok Build CLI not found: $GROK_CMD"
@@ -214,7 +319,17 @@ fi
214
319
  # Preserve which route actually answered without changing the shared schema.
215
320
  if [[ -s "$OUTPUT_FILE" ]]; then
216
321
  response_tmp=$(mktemp)
217
- if jq --arg transport "$TRANSPORT" '.metadata.transport = $transport' \
322
+ if jq --arg transport "$TRANSPORT" \
323
+ --arg cli_version "$GROK_CLI_VERSION" \
324
+ --arg cli_compatibility "$GROK_CLI_COMPATIBILITY" '
325
+ .metadata.transport = $transport |
326
+ if $transport == "cli" and $cli_version != "" then
327
+ .metadata.cli_version = $cli_version |
328
+ .metadata.cli_compatibility = $cli_compatibility
329
+ else
330
+ .
331
+ end
332
+ ' \
218
333
  "$OUTPUT_FILE" > "$response_tmp"; then
219
334
  mv "$response_tmp" "$OUTPUT_FILE"
220
335
  else
@@ -40,9 +40,43 @@ START_TIME=$(get_timestamp_ms)
40
40
 
41
41
  # --- Execution ---
42
42
  TEMP_OUTPUT=$(mktemp)
43
+ KIMI_CLI_VERSION=""
44
+
45
+ observe_kimi_cli_version() {
46
+ local version
47
+ version=$("$KIMI_CMD" --version 2>/dev/null | head -1 || true)
48
+ printf '%s\n' "${version:-unknown}"
49
+ }
50
+
51
+ kimi_cli_supports_required_interface() {
52
+ local help providers flag
53
+
54
+ help=$("$KIMI_CMD" --help 2>&1 || true)
55
+ for flag in --model --prompt --output-format; do
56
+ grep -q -- "$flag" <<< "$help" || return 1
57
+ done
58
+ grep -Eq '^[[:space:]]+provider([[:space:]]|$)' <<< "$help" || return 1
59
+
60
+ # Check the complete prompt-mode parser without running a model request.
61
+ "$KIMI_CMD" \
62
+ --model "$KIMI_MODEL" \
63
+ --prompt "" \
64
+ --output-format stream-json \
65
+ --help >/dev/null 2>&1 || return 1
66
+
67
+ providers=$("$KIMI_CMD" provider list --json 2>/dev/null || true)
68
+ jq -e --arg model "$KIMI_MODEL" '
69
+ .models[$model] != null
70
+ ' <<< "$providers" >/dev/null 2>&1
71
+ }
43
72
 
44
73
  # Check CLI prerequisite
45
74
  check_command "$KIMI_CMD" "Kimi CLI" "curl -L code.kimi.com/install.sh | bash" || exit 1
75
+ KIMI_CLI_VERSION=$(observe_kimi_cli_version)
76
+ kimi_cli_supports_required_interface || {
77
+ log_error "[Kimi] Kimi CLI lacks the required capabilities for model $KIMI_MODEL (reported version: $KIMI_CLI_VERSION)"
78
+ exit 1
79
+ }
46
80
 
47
81
  # Kimi takes the prompt as the -p argument (it does NOT read stdin). The old
48
82
  # `--quiet --input-format text` were NOT real flags on kimi 0.23.6 — commander
@@ -89,5 +123,17 @@ PERSONA_NAME=$(get_persona_name "$CONSULTANT_NAME")
89
123
  process_consultant_response "$CONSULTANT_NAME" "$MODEL_USED" "$PERSONA_NAME" \
90
124
  "$TEMP_OUTPUT" "$OUTPUT_FILE" "$exit_code" "$LATENCY_MS" "" "$FULL_QUERY"
91
125
 
126
+ if [[ -s "$OUTPUT_FILE" ]]; then
127
+ response_tmp=$(mktemp)
128
+ if jq --arg cli_version "$KIMI_CLI_VERSION" '
129
+ .metadata.cli_version = $cli_version |
130
+ .metadata.cli_compatibility = "capability-probed"
131
+ ' "$OUTPUT_FILE" > "$response_tmp"; then
132
+ mv "$response_tmp" "$OUTPUT_FILE"
133
+ else
134
+ rm -f "$response_tmp"
135
+ fi
136
+ fi
137
+
92
138
  cat "$OUTPUT_FILE"
93
139
  exit $exit_code