llm-cli-gateway 1.16.0 → 1.16.2
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/CHANGELOG.md +24 -0
- package/README.md +9 -5
- package/dist/cli-updater.js +16 -8
- package/dist/doctor.d.ts +4 -4
- package/dist/doctor.js +23 -13
- package/dist/index.d.ts +5 -1
- package/dist/index.js +17 -9
- package/dist/provider-login-guidance.js +10 -5
- package/dist/provider-status.js +1 -1
- package/dist/request-helpers.d.ts +10 -3
- package/dist/request-helpers.js +16 -4
- package/dist/upstream-contracts.js +24 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,30 @@ All notable changes to the llm-cli-gateway project.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## [1.16.2] - 2026-05-29 — release formatting follow-up
|
|
8
|
+
|
|
9
|
+
Patch release that keeps the Mistral Vibe CLI contract fixes from `1.16.1`
|
|
10
|
+
and fixes the Prettier check failure on the release commit.
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Formatted the new Vibe session-logging doctor tests so the repository CI
|
|
15
|
+
format gate passes.
|
|
16
|
+
|
|
17
|
+
## [1.16.1] - 2026-05-29 — align Mistral Vibe CLI contract
|
|
18
|
+
|
|
19
|
+
Patch release for the current `mistral-vibe` CLI surface.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Updated Mistral Vibe requests to emit `--output text|json|streaming` instead
|
|
24
|
+
of the removed `--output-format` flag.
|
|
25
|
+
- Kept legacy MCP aliases working by mapping `plain` to `text` and
|
|
26
|
+
`stream-json` to `streaming`.
|
|
27
|
+
- Added `maxTokens` support for Mistral Vibe via `--max-tokens`.
|
|
28
|
+
- Updated Vibe install, upgrade, and doctor guidance for the current
|
|
29
|
+
`mistral-vibe` package and default-on session logging.
|
|
30
|
+
|
|
7
31
|
## [1.16.0] - 2026-05-29 — remove Redis session dependency
|
|
8
32
|
|
|
9
33
|
Feature release that removes the optional Redis/ioredis layer from the
|
package/README.md
CHANGED
|
@@ -253,13 +253,16 @@ grok login # OAuth flow, or set GROK_CODE_XAI_API_KEY
|
|
|
253
253
|
|
|
254
254
|
```bash
|
|
255
255
|
# Pick one — the gateway's cli_upgrade auto-detects which one you used.
|
|
256
|
-
|
|
257
|
-
|
|
256
|
+
curl -LsSf https://mistral.ai/vibe/install.sh | bash
|
|
257
|
+
pip install mistral-vibe
|
|
258
|
+
uv tool install mistral-vibe
|
|
258
259
|
brew install mistral-vibe
|
|
259
260
|
|
|
260
261
|
vibe auth login
|
|
261
|
-
#
|
|
262
|
-
|
|
262
|
+
# Current Vibe defaults session logging to enabled. If an older config disabled it,
|
|
263
|
+
# edit ~/.vibe/config.toml and set:
|
|
264
|
+
# [session_logging]
|
|
265
|
+
# enabled = true
|
|
263
266
|
```
|
|
264
267
|
|
|
265
268
|
Vibe-specific notes:
|
|
@@ -736,7 +739,8 @@ Run a Mistral Vibe agentic coding request. Like `grok_request` in shape, but wit
|
|
|
736
739
|
- `permissionMode`: `default | plan | accept-edits | auto-approve | chat | explore | lean` — emitted as `--agent <mode>`. Defaults to `auto-approve` in programmatic mode.
|
|
737
740
|
- `allowedTools` (string[], optional): One `--enabled-tools <tool>` flag per entry (allow-list only).
|
|
738
741
|
- `disallowedTools` (string[], optional): Accepted for parity with the other providers; ignored at the CLI boundary with a logged warning.
|
|
739
|
-
- `
|
|
742
|
+
- `outputFormat` (string, optional): Vibe 2.x values are `"text"`, `"json"`, or `"streaming"`; legacy aliases `"plain"` and `"stream-json"` are accepted and normalized before spawn.
|
|
743
|
+
- `sessionId` / `resumeLatest` / `createNewSession`: standard session controls. Current Vibe defaults session logging to enabled; if an older config has `[session_logging] enabled = false`, `doctor --json` surfaces an actionable next-action.
|
|
740
744
|
|
|
741
745
|
##### `claude_request_async` / `codex_request_async` / `gemini_request_async` / `grok_request_async` / `mistral_request_async`
|
|
742
746
|
|
package/dist/cli-updater.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import { executeCli } from "./executor.js";
|
|
3
3
|
import { getProviderRuntimeStatus } from "./provider-status.js";
|
|
4
|
+
const MISTRAL_VIBE_PACKAGE = "mistral-vibe";
|
|
5
|
+
const LEGACY_VIBE_PACKAGE = "vibe-cli";
|
|
4
6
|
/**
|
|
5
7
|
* Detect how Vibe was installed on this machine. Vibe does not self-update, so
|
|
6
8
|
* cli_upgrade has to dispatch to the package manager that owns the binary.
|
|
@@ -16,15 +18,19 @@ export function detectMistralInstallMethod(exec = (cmd, args) => {
|
|
|
16
18
|
stdout: result.stdout || "",
|
|
17
19
|
};
|
|
18
20
|
}) {
|
|
19
|
-
const pip = exec("pip", ["show",
|
|
20
|
-
if (pip.exitCode === 0 && /Name:\s*vibe
|
|
21
|
+
const pip = exec("pip", ["show", MISTRAL_VIBE_PACKAGE]);
|
|
22
|
+
if (pip.exitCode === 0 && /Name:\s*mistral-vibe/i.test(pip.stdout)) {
|
|
23
|
+
return "pip";
|
|
24
|
+
}
|
|
25
|
+
const legacyPip = exec("pip", ["show", LEGACY_VIBE_PACKAGE]);
|
|
26
|
+
if (legacyPip.exitCode === 0 && /Name:\s*vibe-cli/i.test(legacyPip.stdout)) {
|
|
21
27
|
return "pip";
|
|
22
28
|
}
|
|
23
29
|
const uv = exec("uv", ["tool", "list"]);
|
|
24
|
-
if (uv.exitCode === 0 && /\
|
|
30
|
+
if (uv.exitCode === 0 && /\b(?:mistral-vibe|vibe-cli|vibe)\b/i.test(uv.stdout)) {
|
|
25
31
|
return "uv";
|
|
26
32
|
}
|
|
27
|
-
const brew = exec("brew", ["list",
|
|
33
|
+
const brew = exec("brew", ["list", MISTRAL_VIBE_PACKAGE]);
|
|
28
34
|
if (brew.exitCode === 0) {
|
|
29
35
|
return "brew";
|
|
30
36
|
}
|
|
@@ -154,7 +160,9 @@ function buildMistralUpgradePlan(normalizedTarget, detectMistral) {
|
|
|
154
160
|
// (we surface it as a no-op plan with `command: ""` so runCliUpgrade can
|
|
155
161
|
// throw before spawning anything).
|
|
156
162
|
if (method === "pip") {
|
|
157
|
-
const pkg = normalizedTarget === "latest"
|
|
163
|
+
const pkg = normalizedTarget === "latest"
|
|
164
|
+
? MISTRAL_VIBE_PACKAGE
|
|
165
|
+
: `${MISTRAL_VIBE_PACKAGE}==${normalizedTarget}`;
|
|
158
166
|
return {
|
|
159
167
|
cli: "mistral",
|
|
160
168
|
target: normalizedTarget,
|
|
@@ -170,7 +178,7 @@ function buildMistralUpgradePlan(normalizedTarget, detectMistral) {
|
|
|
170
178
|
cli: "mistral",
|
|
171
179
|
target: normalizedTarget,
|
|
172
180
|
command: "uv",
|
|
173
|
-
args: ["tool", "upgrade",
|
|
181
|
+
args: ["tool", "upgrade", MISTRAL_VIBE_PACKAGE],
|
|
174
182
|
strategy: "uv-tool-upgrade",
|
|
175
183
|
requiresNetwork: true,
|
|
176
184
|
note: normalizedTarget === "latest"
|
|
@@ -183,7 +191,7 @@ function buildMistralUpgradePlan(normalizedTarget, detectMistral) {
|
|
|
183
191
|
cli: "mistral",
|
|
184
192
|
target: normalizedTarget,
|
|
185
193
|
command: "brew",
|
|
186
|
-
args: ["upgrade",
|
|
194
|
+
args: ["upgrade", MISTRAL_VIBE_PACKAGE],
|
|
187
195
|
strategy: "brew-upgrade",
|
|
188
196
|
requiresNetwork: true,
|
|
189
197
|
note: normalizedTarget === "latest"
|
|
@@ -191,7 +199,7 @@ function buildMistralUpgradePlan(normalizedTarget, detectMistral) {
|
|
|
191
199
|
: "brew upgrade does not honour explicit version targets; running upgrade to latest.",
|
|
192
200
|
};
|
|
193
201
|
}
|
|
194
|
-
throw new Error("Could not detect how Mistral Vibe was installed. Install it via pip (`pip install vibe
|
|
202
|
+
throw new Error("Could not detect how Mistral Vibe was installed. Install it via pip (`pip install mistral-vibe`), uv (`uv tool install mistral-vibe`), or Homebrew (`brew install mistral-vibe`) before running cli_upgrade.");
|
|
195
203
|
}
|
|
196
204
|
async function fallbackCliVersion(cli, args) {
|
|
197
205
|
try {
|
package/dist/doctor.d.ts
CHANGED
|
@@ -51,10 +51,10 @@ export interface GeminiConfigStatus {
|
|
|
51
51
|
next_actions: string[];
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
|
-
* Probe ~/.vibe/config.toml to see whether session_logging is enabled.
|
|
55
|
-
*
|
|
56
|
-
* `[session_logging] enabled =
|
|
57
|
-
* gateway never mutates this file.
|
|
54
|
+
* Probe ~/.vibe/config.toml to see whether session_logging is enabled. Current
|
|
55
|
+
* Mistral Vibe defaults session logging to enabled; an explicit
|
|
56
|
+
* `[session_logging] enabled = false` disables `--continue` / `--resume`.
|
|
57
|
+
* The probe is read-only: the gateway never mutates this file.
|
|
58
58
|
*/
|
|
59
59
|
export declare function checkVibeSessionLogging(home?: string): VibeSessionLoggingStatus;
|
|
60
60
|
/**
|
package/dist/doctor.js
CHANGED
|
@@ -10,10 +10,10 @@ import { loadCacheAwarenessConfig } from "./config.js";
|
|
|
10
10
|
import { computeGlobalCacheStats } from "./cache-stats.js";
|
|
11
11
|
import { FlightRecorder, resolveFlightRecorderDbPath } from "./flight-recorder.js";
|
|
12
12
|
/**
|
|
13
|
-
* Probe ~/.vibe/config.toml to see whether session_logging is enabled.
|
|
14
|
-
*
|
|
15
|
-
* `[session_logging] enabled =
|
|
16
|
-
* gateway never mutates this file.
|
|
13
|
+
* Probe ~/.vibe/config.toml to see whether session_logging is enabled. Current
|
|
14
|
+
* Mistral Vibe defaults session logging to enabled; an explicit
|
|
15
|
+
* `[session_logging] enabled = false` disables `--continue` / `--resume`.
|
|
16
|
+
* The probe is read-only: the gateway never mutates this file.
|
|
17
17
|
*/
|
|
18
18
|
export function checkVibeSessionLogging(home = homedir()) {
|
|
19
19
|
const configPath = join(home, ".vibe", "config.toml");
|
|
@@ -21,26 +21,28 @@ export function checkVibeSessionLogging(home = homedir()) {
|
|
|
21
21
|
return {
|
|
22
22
|
config_path: configPath,
|
|
23
23
|
config_present: false,
|
|
24
|
-
session_logging_enabled:
|
|
25
|
-
note: "~/.vibe/config.toml not found
|
|
24
|
+
session_logging_enabled: true,
|
|
25
|
+
note: "~/.vibe/config.toml not found; current Vibe defaults session_logging.enabled to true. If resume fails, create ~/.vibe/config.toml with [session_logging]\\nenabled = true.",
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
try {
|
|
29
29
|
const text = readFileSync(configPath, "utf8");
|
|
30
30
|
const enabled = parseVibeSessionLoggingEnabled(text);
|
|
31
|
-
if (enabled) {
|
|
31
|
+
if (enabled !== false) {
|
|
32
32
|
return {
|
|
33
33
|
config_path: configPath,
|
|
34
34
|
config_present: true,
|
|
35
35
|
session_logging_enabled: true,
|
|
36
|
-
note:
|
|
36
|
+
note: enabled === true
|
|
37
|
+
? "session_logging.enabled is true; --continue/--resume will work for mistral_request."
|
|
38
|
+
: "session_logging.enabled is not set; current Vibe defaults it to true.",
|
|
37
39
|
};
|
|
38
40
|
}
|
|
39
41
|
return {
|
|
40
42
|
config_path: configPath,
|
|
41
43
|
config_present: true,
|
|
42
44
|
session_logging_enabled: false,
|
|
43
|
-
note: "[session_logging] enabled = false
|
|
45
|
+
note: "[session_logging] enabled = false. Edit ~/.vibe/config.toml so the [session_logging] block sets enabled = true before using mistral_request --resume / --continue.",
|
|
44
46
|
};
|
|
45
47
|
}
|
|
46
48
|
catch (err) {
|
|
@@ -54,7 +56,7 @@ export function checkVibeSessionLogging(home = homedir()) {
|
|
|
54
56
|
}
|
|
55
57
|
}
|
|
56
58
|
/**
|
|
57
|
-
* Tiny TOML probe focused on `[session_logging] enabled =
|
|
59
|
+
* Tiny TOML probe focused on `[session_logging] enabled = ...`. Avoids pulling
|
|
58
60
|
* in the full `toml` parser when only one boolean is needed.
|
|
59
61
|
*/
|
|
60
62
|
function parseVibeSessionLoggingEnabled(text) {
|
|
@@ -73,7 +75,11 @@ function parseVibeSessionLoggingEnabled(text) {
|
|
|
73
75
|
const kv = line.match(/^enabled\s*=\s*(.+)$/);
|
|
74
76
|
if (kv) {
|
|
75
77
|
const value = kv[1].trim().toLowerCase();
|
|
76
|
-
|
|
78
|
+
if (value === "true")
|
|
79
|
+
return true;
|
|
80
|
+
if (value === "false")
|
|
81
|
+
return false;
|
|
82
|
+
return undefined;
|
|
77
83
|
}
|
|
78
84
|
}
|
|
79
85
|
else {
|
|
@@ -81,11 +87,15 @@ function parseVibeSessionLoggingEnabled(text) {
|
|
|
81
87
|
const dotted = line.match(/^session_logging\.enabled\s*=\s*(.+)$/);
|
|
82
88
|
if (dotted) {
|
|
83
89
|
const value = dotted[1].trim().toLowerCase();
|
|
84
|
-
|
|
90
|
+
if (value === "true")
|
|
91
|
+
return true;
|
|
92
|
+
if (value === "false")
|
|
93
|
+
return false;
|
|
94
|
+
return undefined;
|
|
85
95
|
}
|
|
86
96
|
}
|
|
87
97
|
}
|
|
88
|
-
return
|
|
98
|
+
return undefined;
|
|
89
99
|
}
|
|
90
100
|
/**
|
|
91
101
|
* U27: Probe Gemini's project/user config locations.
|
package/dist/index.d.ts
CHANGED
|
@@ -413,6 +413,8 @@ export declare function prepareMistralRequest(params: {
|
|
|
413
413
|
maxTurns?: number;
|
|
414
414
|
/** Phase 4 slice δ: Vibe `--max-price DOLLARS` cumulative-cost cap. */
|
|
415
415
|
maxPrice?: number;
|
|
416
|
+
/** Vibe 2.x: `--max-tokens N` cumulative prompt + completion token cap. */
|
|
417
|
+
maxTokens?: number;
|
|
416
418
|
/** Phase 4 slice ζ: Vibe `--workdir <DIR>` working-directory parity. */
|
|
417
419
|
workingDir?: string;
|
|
418
420
|
/** Phase 4 slice ζ: Vibe `--add-dir <DIR>` repeatable add-dir parity. */
|
|
@@ -429,7 +431,7 @@ export declare function prepareMistralRequest(params: {
|
|
|
429
431
|
* through here, or a fresh-workspace / budgeted run can degrade on
|
|
430
432
|
* the second attempt.
|
|
431
433
|
*/
|
|
432
|
-
export declare function buildMistralRetryPrep(params: Pick<MistralRequestParams, "outputFormat" | "permissionMode" | "effort" | "reasoningEffort" | "allowedTools" | "disallowedTools" | "approvalStrategy" | "trust" | "maxTurns" | "maxPrice" | "workingDir" | "addDir"> & {
|
|
434
|
+
export declare function buildMistralRetryPrep(params: Pick<MistralRequestParams, "outputFormat" | "permissionMode" | "effort" | "reasoningEffort" | "allowedTools" | "disallowedTools" | "approvalStrategy" | "trust" | "maxTurns" | "maxPrice" | "maxTokens" | "workingDir" | "addDir"> & {
|
|
433
435
|
effectivePrompt: string;
|
|
434
436
|
}, recoveryModel: string): {
|
|
435
437
|
args: string[];
|
|
@@ -557,6 +559,8 @@ export interface MistralRequestParams {
|
|
|
557
559
|
maxTurns?: number;
|
|
558
560
|
/** Phase 4 slice δ: Vibe `--max-price DOLLARS` cumulative-cost cap. */
|
|
559
561
|
maxPrice?: number;
|
|
562
|
+
/** Vibe 2.x: `--max-tokens N` cumulative prompt + completion token cap. */
|
|
563
|
+
maxTokens?: number;
|
|
560
564
|
/** Phase 4 slice ζ: Vibe `--workdir <DIR>` working-directory parity. */
|
|
561
565
|
workingDir?: string;
|
|
562
566
|
/** Phase 4 slice ζ: Vibe `--add-dir <DIR>` repeatable add-dir parity. */
|
package/dist/index.js
CHANGED
|
@@ -165,7 +165,7 @@ Other: list_models, cli_versions, upstream_contracts, cli_upgrade, approval_list
|
|
|
165
165
|
|
|
166
166
|
Key behaviors:
|
|
167
167
|
- Sync auto-defers at ${SYNC_DEADLINE_MS}ms. Poll deferred jobs via llm_job_status/llm_job_result.
|
|
168
|
-
- Sessions: Claude --continue, Gemini --resume, Grok --resume/--continue, Mistral --resume/--continue (
|
|
168
|
+
- Sessions: Claude --continue, Gemini --resume, Grok --resume/--continue, Mistral --resume/--continue (current Vibe defaults session logging on; doctor flags explicit session_logging.enabled=false), Codex \`exec resume <ID>\` / \`exec resume --last\` (all real CLI continuity). For Codex, sessionId must be a real Codex UUID (from ~/.codex/sessions/); gateway-generated gw-* IDs are rejected.
|
|
169
169
|
- Approval gates: opt-in via approvalStrategy:"mcp_managed".
|
|
170
170
|
- Idle timeout kills stuck processes (default 10min, configurable via idleTimeoutMs).
|
|
171
171
|
|
|
@@ -1766,6 +1766,7 @@ export function prepareMistralRequest(params, runtime = resolveGatewayServerRunt
|
|
|
1766
1766
|
trust: params.trust,
|
|
1767
1767
|
maxTurns: params.maxTurns,
|
|
1768
1768
|
maxPrice: params.maxPrice,
|
|
1769
|
+
maxTokens: params.maxTokens,
|
|
1769
1770
|
workingDir: params.workingDir,
|
|
1770
1771
|
addDir: params.addDir,
|
|
1771
1772
|
});
|
|
@@ -1822,6 +1823,7 @@ export function buildMistralRetryPrep(params, recoveryModel) {
|
|
|
1822
1823
|
trust: params.trust,
|
|
1823
1824
|
maxTurns: params.maxTurns,
|
|
1824
1825
|
maxPrice: params.maxPrice,
|
|
1826
|
+
maxTokens: params.maxTokens,
|
|
1825
1827
|
workingDir: params.workingDir,
|
|
1826
1828
|
addDir: params.addDir,
|
|
1827
1829
|
});
|
|
@@ -2428,6 +2430,7 @@ export async function handleMistralRequest(deps, params) {
|
|
|
2428
2430
|
trust: params.trust,
|
|
2429
2431
|
maxTurns: params.maxTurns,
|
|
2430
2432
|
maxPrice: params.maxPrice,
|
|
2433
|
+
maxTokens: params.maxTokens,
|
|
2431
2434
|
workingDir: params.workingDir,
|
|
2432
2435
|
addDir: params.addDir,
|
|
2433
2436
|
}, runtime);
|
|
@@ -2578,6 +2581,7 @@ export async function handleMistralRequestAsync(deps, params) {
|
|
|
2578
2581
|
trust: params.trust,
|
|
2579
2582
|
maxTurns: params.maxTurns,
|
|
2580
2583
|
maxPrice: params.maxPrice,
|
|
2584
|
+
maxTokens: params.maxTokens,
|
|
2581
2585
|
workingDir: params.workingDir,
|
|
2582
2586
|
addDir: params.addDir,
|
|
2583
2587
|
}, runtime);
|
|
@@ -3761,13 +3765,13 @@ export function createGatewayServer(deps = {}) {
|
|
|
3761
3765
|
.optional()
|
|
3762
3766
|
.describe("Model alias (e.g. mistral-medium-3.5, latest). Resolved alias is injected via VIBE_ACTIVE_MODEL env var; Vibe has no --model flag."),
|
|
3763
3767
|
outputFormat: z
|
|
3764
|
-
.enum(["plain", "json", "stream-json"])
|
|
3768
|
+
.enum(["text", "plain", "json", "streaming", "stream-json"])
|
|
3765
3769
|
.optional()
|
|
3766
|
-
.describe("Output format (
|
|
3770
|
+
.describe("Output format for Vibe 2.x (text|json|streaming). Legacy aliases plain→text and stream-json→streaming are accepted."),
|
|
3767
3771
|
sessionId: z
|
|
3768
3772
|
.string()
|
|
3769
3773
|
.optional()
|
|
3770
|
-
.describe("Session ID (user-provided CLI handle for --resume).
|
|
3774
|
+
.describe("Session ID (user-provided CLI handle for --resume). Current Vibe defaults session logging on; doctor flags explicit [session_logging] enabled = false."),
|
|
3771
3775
|
resumeLatest: z
|
|
3772
3776
|
.boolean()
|
|
3773
3777
|
.default(false)
|
|
@@ -3822,6 +3826,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
3822
3826
|
.describe("Emit `--trust` so Vibe trusts the cwd for this invocation only (not persisted to trusted_folders.toml) and skips the interactive trust prompt (Phase 4 slice γ)."),
|
|
3823
3827
|
maxTurns: MAX_TURNS_SCHEMA.optional().describe("Vibe `--max-turns N`: cap the agent-loop iteration count (programmatic mode only, Phase 4 slice δ). Bounded to safe integers ≤ 10000."),
|
|
3824
3828
|
maxPrice: MAX_PRICE_SCHEMA.optional().describe("Vibe `--max-price DOLLARS`: interrupt the session when cumulative cost crosses this cap (programmatic mode only, Phase 4 slice δ). Bounded to finite values ≤ 10000 USD."),
|
|
3829
|
+
maxTokens: MAX_TURNS_SCHEMA.optional().describe("Vibe `--max-tokens N`: cap cumulative prompt + completion tokens for the session (programmatic mode only). Bounded to safe integers ≤ 10000."),
|
|
3825
3830
|
// Phase 4 slice ζ — Vibe working-directory + additional-dirs parity.
|
|
3826
3831
|
workingDir: z
|
|
3827
3832
|
.string()
|
|
@@ -3833,7 +3838,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
3833
3838
|
.optional()
|
|
3834
3839
|
.describe("Vibe --add-dir <DIR>: additional writable workspace directories. Each entry is emitted as its own --add-dir instance (Vibe states this flag may be specified multiple times)."),
|
|
3835
3840
|
worktree: WORKTREE_SCHEMA.optional(),
|
|
3836
|
-
}, async ({ prompt, promptParts, model, outputFormat, sessionId, resumeLatest, createNewSession, permissionMode, effort, reasoningEffort, approvalStrategy, approvalPolicy, mcpServers, allowedTools, disallowedTools, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, trust, maxTurns, maxPrice, workingDir, addDir, worktree, }) => {
|
|
3841
|
+
}, async ({ prompt, promptParts, model, outputFormat, sessionId, resumeLatest, createNewSession, permissionMode, effort, reasoningEffort, approvalStrategy, approvalPolicy, mcpServers, allowedTools, disallowedTools, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, trust, maxTurns, maxPrice, maxTokens, workingDir, addDir, worktree, }) => {
|
|
3837
3842
|
return handleMistralRequest({ sessionManager, logger, runtime }, {
|
|
3838
3843
|
prompt,
|
|
3839
3844
|
promptParts,
|
|
@@ -3858,6 +3863,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
3858
3863
|
trust,
|
|
3859
3864
|
maxTurns,
|
|
3860
3865
|
maxPrice,
|
|
3866
|
+
maxTokens,
|
|
3861
3867
|
workingDir,
|
|
3862
3868
|
addDir,
|
|
3863
3869
|
worktree,
|
|
@@ -4482,13 +4488,13 @@ export function createGatewayServer(deps = {}) {
|
|
|
4482
4488
|
.optional()
|
|
4483
4489
|
.describe("Model alias (resolved into VIBE_ACTIVE_MODEL env var — Vibe has no --model flag)"),
|
|
4484
4490
|
outputFormat: z
|
|
4485
|
-
.enum(["plain", "json", "stream-json"])
|
|
4491
|
+
.enum(["text", "plain", "json", "streaming", "stream-json"])
|
|
4486
4492
|
.optional()
|
|
4487
|
-
.describe("Output format (
|
|
4493
|
+
.describe("Output format for Vibe 2.x (text|json|streaming). Legacy aliases plain→text and stream-json→streaming are accepted."),
|
|
4488
4494
|
sessionId: z
|
|
4489
4495
|
.string()
|
|
4490
4496
|
.optional()
|
|
4491
|
-
.describe("Session ID (user-provided CLI handle for --resume).
|
|
4497
|
+
.describe("Session ID (user-provided CLI handle for --resume). Current Vibe defaults session logging on; doctor flags explicit [session_logging] enabled = false."),
|
|
4492
4498
|
resumeLatest: z
|
|
4493
4499
|
.boolean()
|
|
4494
4500
|
.default(false)
|
|
@@ -4542,6 +4548,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
4542
4548
|
.describe("Emit `--trust` so Vibe trusts the cwd for this invocation only (not persisted to trusted_folders.toml) and skips the interactive trust prompt (Phase 4 slice γ)."),
|
|
4543
4549
|
maxTurns: MAX_TURNS_SCHEMA.optional().describe("Vibe `--max-turns N`: cap the agent-loop iteration count (programmatic mode only, Phase 4 slice δ). Bounded to safe integers ≤ 10000."),
|
|
4544
4550
|
maxPrice: MAX_PRICE_SCHEMA.optional().describe("Vibe `--max-price DOLLARS`: interrupt the session when cumulative cost crosses this cap (programmatic mode only, Phase 4 slice δ). Bounded to finite values ≤ 10000 USD."),
|
|
4551
|
+
maxTokens: MAX_TURNS_SCHEMA.optional().describe("Vibe `--max-tokens N`: cap cumulative prompt + completion tokens for the session (programmatic mode only). Bounded to safe integers ≤ 10000."),
|
|
4545
4552
|
// Phase 4 slice ζ — Vibe working-directory + additional-dirs parity.
|
|
4546
4553
|
workingDir: z
|
|
4547
4554
|
.string()
|
|
@@ -4553,7 +4560,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
4553
4560
|
.optional()
|
|
4554
4561
|
.describe("Vibe --add-dir <DIR>: additional writable workspace directories. Each entry is emitted as its own --add-dir instance."),
|
|
4555
4562
|
worktree: WORKTREE_SCHEMA.optional(),
|
|
4556
|
-
}, async ({ prompt, promptParts, model, outputFormat, sessionId, resumeLatest, createNewSession, permissionMode, effort, reasoningEffort, approvalStrategy, approvalPolicy, mcpServers, allowedTools, disallowedTools, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, trust, maxTurns, maxPrice, workingDir, addDir, worktree, }) => {
|
|
4563
|
+
}, async ({ prompt, promptParts, model, outputFormat, sessionId, resumeLatest, createNewSession, permissionMode, effort, reasoningEffort, approvalStrategy, approvalPolicy, mcpServers, allowedTools, disallowedTools, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, trust, maxTurns, maxPrice, maxTokens, workingDir, addDir, worktree, }) => {
|
|
4557
4564
|
return handleMistralRequestAsync({ sessionManager, asyncJobManager, logger, runtime }, {
|
|
4558
4565
|
prompt,
|
|
4559
4566
|
promptParts,
|
|
@@ -4577,6 +4584,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
4577
4584
|
trust,
|
|
4578
4585
|
maxTurns,
|
|
4579
4586
|
maxPrice,
|
|
4587
|
+
maxTokens,
|
|
4580
4588
|
workingDir,
|
|
4581
4589
|
addDir,
|
|
4582
4590
|
worktree,
|
|
@@ -76,17 +76,22 @@ const GUIDANCE = {
|
|
|
76
76
|
displayName: "Mistral Vibe CLI",
|
|
77
77
|
install: {
|
|
78
78
|
summary: "Install Mistral Vibe CLI via pip, uv, or Homebrew (Vibe does not self-update; cli_upgrade dispatches to the installer it detects).",
|
|
79
|
-
commands: [
|
|
80
|
-
|
|
79
|
+
commands: [
|
|
80
|
+
"curl -LsSf https://mistral.ai/vibe/install.sh | bash",
|
|
81
|
+
"pip install mistral-vibe",
|
|
82
|
+
"uv tool install mistral-vibe",
|
|
83
|
+
"brew install mistral-vibe",
|
|
84
|
+
],
|
|
85
|
+
documentationUrl: "https://docs.mistral.ai/mistral-vibe/overview",
|
|
81
86
|
},
|
|
82
87
|
login: {
|
|
83
|
-
summary: "Sign in through Mistral's official auth flow
|
|
84
|
-
commands: ["vibe auth login"
|
|
88
|
+
summary: "Sign in through Mistral's official auth flow. Current Vibe defaults session logging to enabled; if an older config disabled it, edit ~/.vibe/config.toml and set [session_logging] enabled = true.",
|
|
89
|
+
commands: ["vibe auth login"],
|
|
85
90
|
credentialHandling: "Do not paste Mistral API keys, OAuth tokens, or ~/.vibe/credentials into the gateway or a remote chat.",
|
|
86
91
|
},
|
|
87
92
|
verification: {
|
|
88
93
|
command: "vibe --version",
|
|
89
|
-
expected: "Vibe CLI is installed; doctor
|
|
94
|
+
expected: "Vibe CLI is installed; doctor checks ~/.vibe/config.toml for an explicit session_logging.enabled=false override",
|
|
90
95
|
},
|
|
91
96
|
},
|
|
92
97
|
};
|
package/dist/provider-status.js
CHANGED
|
@@ -12,7 +12,7 @@ const VERSION_ARGS = {
|
|
|
12
12
|
grok: ["--version"],
|
|
13
13
|
mistral: ["--version"],
|
|
14
14
|
};
|
|
15
|
-
// Mistral Vibe ships as the `vibe` binary (PyPI package vibe
|
|
15
|
+
// Mistral Vibe ships as the `vibe` binary (PyPI package mistral-vibe); the gateway
|
|
16
16
|
// uses `mistral` as the provider key but invokes `vibe` on the shell.
|
|
17
17
|
export const PROVIDER_COMMANDS = {
|
|
18
18
|
claude: "claude",
|
|
@@ -71,9 +71,9 @@ export declare function resolveGrokSessionArgs(opts: {
|
|
|
71
71
|
/**
|
|
72
72
|
* Mistral Vibe-specific resume args.
|
|
73
73
|
*
|
|
74
|
-
* Vibe
|
|
75
|
-
*
|
|
76
|
-
*
|
|
74
|
+
* Current Vibe defaults session logging on; older configs can explicitly set
|
|
75
|
+
* `[session_logging] enabled = false`. The doctor checks that toggle before
|
|
76
|
+
* callers rely on session continuity; this pure helper just emits the args.
|
|
77
77
|
*
|
|
78
78
|
* The args shape mirrors Grok (`--continue` for latest, `--resume <id>` for a
|
|
79
79
|
* specific session) because Vibe exposes the same surface for its session log.
|
|
@@ -125,6 +125,11 @@ export interface PrepareMistralRequestInput {
|
|
|
125
125
|
* only).
|
|
126
126
|
*/
|
|
127
127
|
maxPrice?: number;
|
|
128
|
+
/**
|
|
129
|
+
* Vibe 2.x supports `--max-tokens N` in programmatic mode, wired through to
|
|
130
|
+
* `run_programmatic(max_session_tokens=...)`.
|
|
131
|
+
*/
|
|
132
|
+
maxTokens?: number;
|
|
128
133
|
/**
|
|
129
134
|
* Phase 4 slice ζ: emit `--workdir <DIR>` so Vibe changes into the named
|
|
130
135
|
* directory before running. Single value (Vibe accepts one --workdir).
|
|
@@ -148,6 +153,8 @@ export interface PrepareMistralRequestResult {
|
|
|
148
153
|
* - Model is selected via `VIBE_ACTIVE_MODEL` env var (NOT a `--model` flag).
|
|
149
154
|
* - Permission mode emits `--agent <mode>` (defaults to `auto-approve` when unset).
|
|
150
155
|
* - Allowed tools emit `--enabled-tools <tool>` once per tool (allowlist only).
|
|
156
|
+
* - Output format emits `--output <text|json|streaming>` (legacy gateway
|
|
157
|
+
* aliases `plain` and `stream-json` are normalized before spawn).
|
|
151
158
|
* - Disallowed tools are accepted but ignored at the CLI boundary.
|
|
152
159
|
*/
|
|
153
160
|
export declare function prepareMistralRequest(input: PrepareMistralRequestInput): PrepareMistralRequestResult;
|
package/dist/request-helpers.js
CHANGED
|
@@ -100,9 +100,9 @@ export function resolveGrokSessionArgs(opts) {
|
|
|
100
100
|
/**
|
|
101
101
|
* Mistral Vibe-specific resume args.
|
|
102
102
|
*
|
|
103
|
-
* Vibe
|
|
104
|
-
*
|
|
105
|
-
*
|
|
103
|
+
* Current Vibe defaults session logging on; older configs can explicitly set
|
|
104
|
+
* `[session_logging] enabled = false`. The doctor checks that toggle before
|
|
105
|
+
* callers rely on session continuity; this pure helper just emits the args.
|
|
106
106
|
*
|
|
107
107
|
* The args shape mirrors Grok (`--continue` for latest, `--resume <id>` for a
|
|
108
108
|
* specific session) because Vibe exposes the same surface for its session log.
|
|
@@ -151,6 +151,8 @@ export const MISTRAL_DEFAULT_AGENT_MODE = "auto-approve";
|
|
|
151
151
|
* - Model is selected via `VIBE_ACTIVE_MODEL` env var (NOT a `--model` flag).
|
|
152
152
|
* - Permission mode emits `--agent <mode>` (defaults to `auto-approve` when unset).
|
|
153
153
|
* - Allowed tools emit `--enabled-tools <tool>` once per tool (allowlist only).
|
|
154
|
+
* - Output format emits `--output <text|json|streaming>` (legacy gateway
|
|
155
|
+
* aliases `plain` and `stream-json` are normalized before spawn).
|
|
154
156
|
* - Disallowed tools are accepted but ignored at the CLI boundary.
|
|
155
157
|
*/
|
|
156
158
|
export function prepareMistralRequest(input) {
|
|
@@ -160,7 +162,7 @@ export function prepareMistralRequest(input) {
|
|
|
160
162
|
env.VIBE_ACTIVE_MODEL = input.resolvedModel;
|
|
161
163
|
}
|
|
162
164
|
if (input.outputFormat) {
|
|
163
|
-
args.push("--output
|
|
165
|
+
args.push("--output", normalizeMistralOutputFormat(input.outputFormat));
|
|
164
166
|
}
|
|
165
167
|
const mode = input.permissionMode ?? MISTRAL_DEFAULT_AGENT_MODE;
|
|
166
168
|
args.push("--agent", mode);
|
|
@@ -185,6 +187,9 @@ export function prepareMistralRequest(input) {
|
|
|
185
187
|
if (input.maxPrice !== undefined) {
|
|
186
188
|
args.push("--max-price", String(input.maxPrice));
|
|
187
189
|
}
|
|
190
|
+
if (input.maxTokens !== undefined) {
|
|
191
|
+
args.push("--max-tokens", String(input.maxTokens));
|
|
192
|
+
}
|
|
188
193
|
if (input.workingDir) {
|
|
189
194
|
args.push("--workdir", input.workingDir);
|
|
190
195
|
}
|
|
@@ -196,6 +201,13 @@ export function prepareMistralRequest(input) {
|
|
|
196
201
|
const ignoredDisallowedTools = Boolean(input.disallowedTools && input.disallowedTools.length > 0);
|
|
197
202
|
return { args, env, ignoredDisallowedTools };
|
|
198
203
|
}
|
|
204
|
+
function normalizeMistralOutputFormat(format) {
|
|
205
|
+
if (format === "plain")
|
|
206
|
+
return "text";
|
|
207
|
+
if (format === "stream-json")
|
|
208
|
+
return "streaming";
|
|
209
|
+
return format;
|
|
210
|
+
}
|
|
199
211
|
//──────────────────────────────────────────────────────────────────────────────
|
|
200
212
|
// U24: Permission / approval mode parity helpers
|
|
201
213
|
//──────────────────────────────────────────────────────────────────────────────
|
|
@@ -604,15 +604,16 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
604
604
|
// Phase 4 slice δ
|
|
605
605
|
"maxTurns",
|
|
606
606
|
"maxPrice",
|
|
607
|
+
"maxTokens",
|
|
607
608
|
// Phase 4 slice ζ
|
|
608
609
|
"workingDir",
|
|
609
610
|
"addDir",
|
|
610
611
|
],
|
|
611
612
|
flags: {
|
|
612
613
|
"-p": { arity: "one", description: "Prompt text" },
|
|
613
|
-
"--output
|
|
614
|
+
"--output": {
|
|
614
615
|
arity: "one",
|
|
615
|
-
values: ["
|
|
616
|
+
values: ["text", "json", "streaming"],
|
|
616
617
|
description: "Output format",
|
|
617
618
|
},
|
|
618
619
|
"--agent": {
|
|
@@ -641,6 +642,11 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
641
642
|
pattern: /^(0|[1-9][0-9]*)(\.[0-9]+)?$/,
|
|
642
643
|
description: "Cumulative cost cap in USD (Phase 4 slice δ, programmatic mode only)",
|
|
643
644
|
},
|
|
645
|
+
"--max-tokens": {
|
|
646
|
+
arity: "one",
|
|
647
|
+
pattern: /^[1-9][0-9]*$/,
|
|
648
|
+
description: "Cumulative prompt + completion token cap (Vibe 2.x programmatic mode)",
|
|
649
|
+
},
|
|
644
650
|
"--workdir": {
|
|
645
651
|
arity: "one",
|
|
646
652
|
description: "Working directory for the invocation (Phase 4 slice ζ)",
|
|
@@ -686,6 +692,22 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
686
692
|
env: { VIBE_ACTIVE_MODEL: "mistral-medium-3.5" },
|
|
687
693
|
expect: "pass",
|
|
688
694
|
},
|
|
695
|
+
{
|
|
696
|
+
id: "mistral-output-streaming-and-max-tokens",
|
|
697
|
+
description: "Vibe 2.x: --output streaming and --max-tokens are accepted",
|
|
698
|
+
args: [
|
|
699
|
+
"-p",
|
|
700
|
+
"hello",
|
|
701
|
+
"--agent",
|
|
702
|
+
"auto-approve",
|
|
703
|
+
"--output",
|
|
704
|
+
"streaming",
|
|
705
|
+
"--max-tokens",
|
|
706
|
+
"1000",
|
|
707
|
+
],
|
|
708
|
+
env: { VIBE_ACTIVE_MODEL: "mistral-medium-3.5" },
|
|
709
|
+
expect: "pass",
|
|
710
|
+
},
|
|
689
711
|
{
|
|
690
712
|
id: "mistral-max-price-scientific-notation",
|
|
691
713
|
description: "Phase 4 slice δ: scientific-notation --max-price is rejected by contract pattern (matches MAX_PRICE_SCHEMA bounds)",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llm-cli-gateway",
|
|
3
|
-
"version": "1.16.
|
|
3
|
+
"version": "1.16.2",
|
|
4
4
|
"mcpName": "io.github.verivus-oss/llm-cli-gateway",
|
|
5
5
|
"description": "MCP server providing unified access to Claude Code, Codex, Gemini, Grok, and Mistral Vibe CLIs with session management, retry logic, async job orchestration, durable job results, and cross-LLM validation.",
|
|
6
6
|
"license": "MIT",
|