llm-cli-gateway 1.1.0 → 1.5.4
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 +87 -0
- package/README.md +226 -9
- package/dist/approval-manager.d.ts +1 -1
- package/dist/async-job-manager.d.ts +75 -4
- package/dist/async-job-manager.js +303 -19
- package/dist/auth.d.ts +15 -0
- package/dist/auth.js +46 -0
- package/dist/cli-updater.d.ts +55 -0
- package/dist/cli-updater.js +248 -0
- package/dist/codex-json-parser.d.ts +34 -0
- package/dist/codex-json-parser.js +105 -0
- package/dist/doctor.d.ts +110 -0
- package/dist/doctor.js +280 -0
- package/dist/endpoint-exposure.d.ts +22 -0
- package/dist/endpoint-exposure.js +231 -0
- package/dist/executor.d.ts +2 -0
- package/dist/executor.js +2 -2
- package/dist/flight-recorder.d.ts +3 -1
- package/dist/flight-recorder.js +31 -2
- package/dist/gateway-server.d.ts +2 -0
- package/dist/gateway-server.js +1 -0
- package/dist/gemini-json-parser.d.ts +21 -0
- package/dist/gemini-json-parser.js +47 -0
- package/dist/health.d.ts +7 -0
- package/dist/health.js +22 -0
- package/dist/http-transport.d.ts +22 -0
- package/dist/http-transport.js +164 -0
- package/dist/index.d.ts +210 -2
- package/dist/index.js +2880 -1037
- package/dist/job-store.d.ts +84 -0
- package/dist/job-store.js +251 -0
- package/dist/logger.d.ts +9 -0
- package/dist/logger.js +14 -0
- package/dist/model-registry.d.ts +14 -0
- package/dist/model-registry.js +478 -134
- package/dist/provider-login-guidance.d.ts +21 -0
- package/dist/provider-login-guidance.js +98 -0
- package/dist/provider-status.d.ts +41 -0
- package/dist/provider-status.js +203 -0
- package/dist/request-helpers.d.ts +525 -4
- package/dist/request-helpers.js +653 -0
- package/dist/resources.js +88 -0
- package/dist/session-manager-pg.js +2 -0
- package/dist/session-manager.d.ts +1 -1
- package/dist/session-manager.js +3 -1
- package/dist/validation-normalizer.d.ts +23 -0
- package/dist/validation-normalizer.js +79 -0
- package/dist/validation-orchestrator.d.ts +47 -0
- package/dist/validation-orchestrator.js +145 -0
- package/dist/validation-prompts.d.ts +15 -0
- package/dist/validation-prompts.js +52 -0
- package/dist/validation-report.d.ts +57 -0
- package/dist/validation-report.js +129 -0
- package/dist/validation-tools.d.ts +7 -0
- package/dist/validation-tools.js +198 -0
- package/package.json +16 -6
- package/setup/status.schema.json +271 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { executeCli } from "./executor.js";
|
|
3
|
+
import { getProviderRuntimeStatus } from "./provider-status.js";
|
|
4
|
+
/**
|
|
5
|
+
* Detect how Vibe was installed on this machine. Vibe does not self-update, so
|
|
6
|
+
* cli_upgrade has to dispatch to the package manager that owns the binary.
|
|
7
|
+
*
|
|
8
|
+
* Probe order: pip → uv → brew. The first one that returns a positive signal
|
|
9
|
+
* wins; if none do, callers should surface an actionable error rather than
|
|
10
|
+
* blindly running `vibe update` (a command that does not exist).
|
|
11
|
+
*/
|
|
12
|
+
export function detectMistralInstallMethod(exec = (cmd, args) => {
|
|
13
|
+
const result = spawnSync(cmd, args, { encoding: "utf8", timeout: 5_000, windowsHide: true });
|
|
14
|
+
return {
|
|
15
|
+
exitCode: typeof result.status === "number" ? result.status : null,
|
|
16
|
+
stdout: result.stdout || "",
|
|
17
|
+
};
|
|
18
|
+
}) {
|
|
19
|
+
const pip = exec("pip", ["show", "vibe-cli"]);
|
|
20
|
+
if (pip.exitCode === 0 && /Name:\s*vibe-cli/i.test(pip.stdout)) {
|
|
21
|
+
return "pip";
|
|
22
|
+
}
|
|
23
|
+
const uv = exec("uv", ["tool", "list"]);
|
|
24
|
+
if (uv.exitCode === 0 && /\bvibe(?:-cli)?\b/i.test(uv.stdout)) {
|
|
25
|
+
return "uv";
|
|
26
|
+
}
|
|
27
|
+
const brew = exec("brew", ["list", "mistral-vibe"]);
|
|
28
|
+
if (brew.exitCode === 0) {
|
|
29
|
+
return "brew";
|
|
30
|
+
}
|
|
31
|
+
return "unknown";
|
|
32
|
+
}
|
|
33
|
+
const VERSION_ARGS = {
|
|
34
|
+
claude: ["--version"],
|
|
35
|
+
codex: ["--version"],
|
|
36
|
+
gemini: ["--version"],
|
|
37
|
+
grok: ["--version"],
|
|
38
|
+
mistral: ["--version"],
|
|
39
|
+
};
|
|
40
|
+
const NPM_PACKAGES = {
|
|
41
|
+
codex: "@openai/codex",
|
|
42
|
+
gemini: "@google/gemini-cli",
|
|
43
|
+
};
|
|
44
|
+
export function buildCliUpgradePlan(cli, target = "latest", detectMistral = detectMistralInstallMethod) {
|
|
45
|
+
const normalizedTarget = normalizeTarget(target);
|
|
46
|
+
if (cli === "mistral") {
|
|
47
|
+
return buildMistralUpgradePlan(normalizedTarget, detectMistral);
|
|
48
|
+
}
|
|
49
|
+
if (cli === "claude") {
|
|
50
|
+
if (normalizedTarget === "latest") {
|
|
51
|
+
return {
|
|
52
|
+
cli,
|
|
53
|
+
target: normalizedTarget,
|
|
54
|
+
command: "claude",
|
|
55
|
+
args: ["update"],
|
|
56
|
+
strategy: "self-update",
|
|
57
|
+
requiresNetwork: true,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
cli,
|
|
62
|
+
target: normalizedTarget,
|
|
63
|
+
command: "claude",
|
|
64
|
+
args: ["install", normalizedTarget],
|
|
65
|
+
strategy: "self-update",
|
|
66
|
+
requiresNetwork: true,
|
|
67
|
+
note: "Claude Code supports explicit install targets through 'claude install <target>'.",
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (cli === "grok") {
|
|
71
|
+
if (normalizedTarget === "latest") {
|
|
72
|
+
return {
|
|
73
|
+
cli,
|
|
74
|
+
target: normalizedTarget,
|
|
75
|
+
command: "grok",
|
|
76
|
+
args: ["update"],
|
|
77
|
+
strategy: "self-update",
|
|
78
|
+
requiresNetwork: true,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
cli,
|
|
83
|
+
target: normalizedTarget,
|
|
84
|
+
command: "grok",
|
|
85
|
+
args: ["update", "--version", normalizedTarget],
|
|
86
|
+
strategy: "self-update",
|
|
87
|
+
requiresNetwork: true,
|
|
88
|
+
note: "Grok CLI supports explicit version targets via 'grok update --version <target>'.",
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (cli === "codex" && normalizedTarget === "latest") {
|
|
92
|
+
return {
|
|
93
|
+
cli,
|
|
94
|
+
target: normalizedTarget,
|
|
95
|
+
command: "codex",
|
|
96
|
+
args: ["update"],
|
|
97
|
+
strategy: "self-update",
|
|
98
|
+
requiresNetwork: true,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const packageName = cli === "codex" ? NPM_PACKAGES.codex : NPM_PACKAGES.gemini;
|
|
102
|
+
return {
|
|
103
|
+
cli,
|
|
104
|
+
target: normalizedTarget,
|
|
105
|
+
command: "npm",
|
|
106
|
+
args: ["install", "-g", `${packageName}@${normalizedTarget}`],
|
|
107
|
+
strategy: "npm-global-install",
|
|
108
|
+
requiresNetwork: true,
|
|
109
|
+
note: cli === "codex"
|
|
110
|
+
? "Explicit Codex targets use the documented npm package path; latest can use 'codex update'."
|
|
111
|
+
: "Gemini CLI does not expose a self-update command in the gateway-supported CLI surface, so upgrades use npm.",
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
export async function getCliVersion(cli) {
|
|
115
|
+
const args = VERSION_ARGS[cli];
|
|
116
|
+
try {
|
|
117
|
+
const status = getProviderRuntimeStatus(cli);
|
|
118
|
+
return {
|
|
119
|
+
cli,
|
|
120
|
+
command: cli,
|
|
121
|
+
args,
|
|
122
|
+
installed: status.installed,
|
|
123
|
+
version: status.version || undefined,
|
|
124
|
+
loginStatus: status.loginStatus,
|
|
125
|
+
loginGuidance: status.guidance.login,
|
|
126
|
+
stdout: status.version || "",
|
|
127
|
+
stderr: "",
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
const result = await fallbackCliVersion(cli, args);
|
|
132
|
+
if (result)
|
|
133
|
+
return result;
|
|
134
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
135
|
+
return {
|
|
136
|
+
cli,
|
|
137
|
+
command: cli,
|
|
138
|
+
args,
|
|
139
|
+
installed: false,
|
|
140
|
+
stdout: "",
|
|
141
|
+
stderr: "",
|
|
142
|
+
error: message,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
export async function getCliVersions(cli) {
|
|
147
|
+
const clis = cli ? [cli] : ["claude", "codex", "gemini", "grok", "mistral"];
|
|
148
|
+
return Promise.all(clis.map(item => getCliVersion(item)));
|
|
149
|
+
}
|
|
150
|
+
function buildMistralUpgradePlan(normalizedTarget, detectMistral) {
|
|
151
|
+
const method = detectMistral();
|
|
152
|
+
// Vibe ships no self-update command. cli_upgrade dispatches to the installer
|
|
153
|
+
// it detects; if none can be detected the caller gets an actionable error
|
|
154
|
+
// (we surface it as a no-op plan with `command: ""` so runCliUpgrade can
|
|
155
|
+
// throw before spawning anything).
|
|
156
|
+
if (method === "pip") {
|
|
157
|
+
const pkg = normalizedTarget === "latest" ? "vibe-cli" : `vibe-cli==${normalizedTarget}`;
|
|
158
|
+
return {
|
|
159
|
+
cli: "mistral",
|
|
160
|
+
target: normalizedTarget,
|
|
161
|
+
command: "pip",
|
|
162
|
+
args: ["install", "-U", pkg],
|
|
163
|
+
strategy: "pip-install",
|
|
164
|
+
requiresNetwork: true,
|
|
165
|
+
note: "Mistral Vibe has no self-update command; gateway detected a pip install.",
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
if (method === "uv") {
|
|
169
|
+
return {
|
|
170
|
+
cli: "mistral",
|
|
171
|
+
target: normalizedTarget,
|
|
172
|
+
command: "uv",
|
|
173
|
+
args: ["tool", "upgrade", "vibe-cli"],
|
|
174
|
+
strategy: "uv-tool-upgrade",
|
|
175
|
+
requiresNetwork: true,
|
|
176
|
+
note: normalizedTarget === "latest"
|
|
177
|
+
? "Mistral Vibe has no self-update command; gateway detected a uv tool install."
|
|
178
|
+
: "uv tool upgrade does not honour explicit version targets; running upgrade to latest.",
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
if (method === "brew") {
|
|
182
|
+
return {
|
|
183
|
+
cli: "mistral",
|
|
184
|
+
target: normalizedTarget,
|
|
185
|
+
command: "brew",
|
|
186
|
+
args: ["upgrade", "mistral-vibe"],
|
|
187
|
+
strategy: "brew-upgrade",
|
|
188
|
+
requiresNetwork: true,
|
|
189
|
+
note: normalizedTarget === "latest"
|
|
190
|
+
? "Mistral Vibe has no self-update command; gateway detected a Homebrew install."
|
|
191
|
+
: "brew upgrade does not honour explicit version targets; running upgrade to latest.",
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
throw new Error("Could not detect how Mistral Vibe was installed. Install it via pip (`pip install vibe-cli`), uv (`uv tool install vibe-cli`), or Homebrew (`brew install mistral-vibe`) before running cli_upgrade.");
|
|
195
|
+
}
|
|
196
|
+
async function fallbackCliVersion(cli, args) {
|
|
197
|
+
try {
|
|
198
|
+
const result = await executeCli(cli, args, { timeout: 15_000 });
|
|
199
|
+
return {
|
|
200
|
+
cli,
|
|
201
|
+
command: cli,
|
|
202
|
+
args,
|
|
203
|
+
installed: true,
|
|
204
|
+
version: extractVersion(result.stdout, result.stderr),
|
|
205
|
+
stdout: result.stdout,
|
|
206
|
+
stderr: result.stderr,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
export async function runCliUpgrade(params) {
|
|
214
|
+
const plan = buildCliUpgradePlan(params.cli, params.target);
|
|
215
|
+
if (params.dryRun) {
|
|
216
|
+
return { dryRun: true, plan };
|
|
217
|
+
}
|
|
218
|
+
params.logger?.info(`Upgrading ${params.cli} CLI`, {
|
|
219
|
+
target: plan.target,
|
|
220
|
+
command: plan.command,
|
|
221
|
+
args: plan.args,
|
|
222
|
+
});
|
|
223
|
+
const result = await executeCli(plan.command, plan.args, {
|
|
224
|
+
timeout: params.timeoutMs ?? 600_000,
|
|
225
|
+
logger: params.logger,
|
|
226
|
+
});
|
|
227
|
+
return {
|
|
228
|
+
dryRun: false,
|
|
229
|
+
plan,
|
|
230
|
+
stdout: result.stdout,
|
|
231
|
+
stderr: result.stderr,
|
|
232
|
+
exitCode: result.code,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function normalizeTarget(target) {
|
|
236
|
+
const normalized = target.trim();
|
|
237
|
+
if (!normalized || normalized.startsWith("-") || /[\u0000-\u001f\u007f\s]/.test(normalized)) {
|
|
238
|
+
throw new Error("Upgrade target must be a non-empty package tag or version without whitespace and cannot start with '-'");
|
|
239
|
+
}
|
|
240
|
+
return normalized;
|
|
241
|
+
}
|
|
242
|
+
function extractVersion(stdout, stderr) {
|
|
243
|
+
const text = `${stdout}\n${stderr}`
|
|
244
|
+
.split(/\r?\n/)
|
|
245
|
+
.map(line => line.trim())
|
|
246
|
+
.find(line => line.length > 0);
|
|
247
|
+
return text || undefined;
|
|
248
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parser for Codex CLI `--json` JSONL event stream.
|
|
3
|
+
*
|
|
4
|
+
* Codex emits one JSON object per line, e.g.:
|
|
5
|
+
* {"type":"thread.started","thread_id":"t-abc"}
|
|
6
|
+
* {"type":"turn.started","turn_id":"u-001"}
|
|
7
|
+
* {"type":"item.started","item":{...}}
|
|
8
|
+
* {"type":"item.completed","item":{"type":"agent_message","text":"..."}}
|
|
9
|
+
* {"type":"turn.completed","usage":{"input_tokens":...,"output_tokens":...,...}}
|
|
10
|
+
* {"type":"turn.failed","error":{...}}
|
|
11
|
+
* {"type":"error","message":"..."}
|
|
12
|
+
*
|
|
13
|
+
* This parser is lenient: malformed lines are skipped, partial streams are
|
|
14
|
+
* tolerated (usage is `undefined` if no turn.completed event arrived), and
|
|
15
|
+
* error events are surfaced.
|
|
16
|
+
*
|
|
17
|
+
* Cost is intentionally NOT computed here — Codex does not price client-side
|
|
18
|
+
* and U23 only plumbs tokens. A future unit can compute cost from the model
|
|
19
|
+
* registry.
|
|
20
|
+
*/
|
|
21
|
+
export interface CodexUsage {
|
|
22
|
+
input_tokens: number;
|
|
23
|
+
output_tokens: number;
|
|
24
|
+
cache_read_tokens?: number;
|
|
25
|
+
cache_creation_tokens?: number;
|
|
26
|
+
cost_usd?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface CodexJsonParseResult {
|
|
29
|
+
usage?: CodexUsage;
|
|
30
|
+
error?: string;
|
|
31
|
+
threadId?: string;
|
|
32
|
+
finalMessage?: string;
|
|
33
|
+
}
|
|
34
|
+
export declare function parseCodexJsonStream(stdout: string): CodexJsonParseResult;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parser for Codex CLI `--json` JSONL event stream.
|
|
3
|
+
*
|
|
4
|
+
* Codex emits one JSON object per line, e.g.:
|
|
5
|
+
* {"type":"thread.started","thread_id":"t-abc"}
|
|
6
|
+
* {"type":"turn.started","turn_id":"u-001"}
|
|
7
|
+
* {"type":"item.started","item":{...}}
|
|
8
|
+
* {"type":"item.completed","item":{"type":"agent_message","text":"..."}}
|
|
9
|
+
* {"type":"turn.completed","usage":{"input_tokens":...,"output_tokens":...,...}}
|
|
10
|
+
* {"type":"turn.failed","error":{...}}
|
|
11
|
+
* {"type":"error","message":"..."}
|
|
12
|
+
*
|
|
13
|
+
* This parser is lenient: malformed lines are skipped, partial streams are
|
|
14
|
+
* tolerated (usage is `undefined` if no turn.completed event arrived), and
|
|
15
|
+
* error events are surfaced.
|
|
16
|
+
*
|
|
17
|
+
* Cost is intentionally NOT computed here — Codex does not price client-side
|
|
18
|
+
* and U23 only plumbs tokens. A future unit can compute cost from the model
|
|
19
|
+
* registry.
|
|
20
|
+
*/
|
|
21
|
+
export function parseCodexJsonStream(stdout) {
|
|
22
|
+
const lines = stdout.split("\n").filter(line => line.trim().length > 0);
|
|
23
|
+
const result = {};
|
|
24
|
+
let lastAgentMessage;
|
|
25
|
+
for (const line of lines) {
|
|
26
|
+
let parsed;
|
|
27
|
+
try {
|
|
28
|
+
parsed = JSON.parse(line);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// Skip preamble/garbage lines that aren't valid JSON.
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (!parsed || typeof parsed !== "object") {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
switch (parsed.type) {
|
|
38
|
+
case "thread.started":
|
|
39
|
+
if (typeof parsed.thread_id === "string") {
|
|
40
|
+
result.threadId = parsed.thread_id;
|
|
41
|
+
}
|
|
42
|
+
break;
|
|
43
|
+
case "turn.completed": {
|
|
44
|
+
const u = parsed.usage;
|
|
45
|
+
if (u && typeof u === "object") {
|
|
46
|
+
const usage = {
|
|
47
|
+
input_tokens: typeof u.input_tokens === "number" ? u.input_tokens : 0,
|
|
48
|
+
output_tokens: typeof u.output_tokens === "number" ? u.output_tokens : 0,
|
|
49
|
+
};
|
|
50
|
+
if (typeof u.cache_read_input_tokens === "number") {
|
|
51
|
+
usage.cache_read_tokens = u.cache_read_input_tokens;
|
|
52
|
+
}
|
|
53
|
+
else if (typeof u.cache_read_tokens === "number") {
|
|
54
|
+
usage.cache_read_tokens = u.cache_read_tokens;
|
|
55
|
+
}
|
|
56
|
+
if (typeof u.cache_creation_input_tokens === "number") {
|
|
57
|
+
usage.cache_creation_tokens = u.cache_creation_input_tokens;
|
|
58
|
+
}
|
|
59
|
+
else if (typeof u.cache_creation_tokens === "number") {
|
|
60
|
+
usage.cache_creation_tokens = u.cache_creation_tokens;
|
|
61
|
+
}
|
|
62
|
+
if (typeof u.cost_usd === "number") {
|
|
63
|
+
usage.cost_usd = u.cost_usd;
|
|
64
|
+
}
|
|
65
|
+
result.usage = usage;
|
|
66
|
+
}
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
case "turn.failed": {
|
|
70
|
+
const err = parsed.error;
|
|
71
|
+
if (typeof err === "string") {
|
|
72
|
+
result.error = err;
|
|
73
|
+
}
|
|
74
|
+
else if (err && typeof err === "object" && typeof err.message === "string") {
|
|
75
|
+
result.error = err.message;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
result.error = "turn failed";
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
case "error":
|
|
83
|
+
if (typeof parsed.message === "string") {
|
|
84
|
+
result.error = parsed.message;
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
case "item.completed": {
|
|
88
|
+
const item = parsed.item;
|
|
89
|
+
if (item &&
|
|
90
|
+
typeof item === "object" &&
|
|
91
|
+
item.type === "agent_message" &&
|
|
92
|
+
typeof item.text === "string") {
|
|
93
|
+
lastAgentMessage = item.text;
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
default:
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (lastAgentMessage !== undefined) {
|
|
102
|
+
result.finalMessage = lastAgentMessage;
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
package/dist/doctor.d.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { type EndpointExposureReport } from "./endpoint-exposure.js";
|
|
2
|
+
import { type ProviderLoginStatus } from "./provider-status.js";
|
|
3
|
+
export interface VibeSessionLoggingStatus {
|
|
4
|
+
config_path: string;
|
|
5
|
+
config_present: boolean;
|
|
6
|
+
session_logging_enabled: boolean;
|
|
7
|
+
note: string;
|
|
8
|
+
}
|
|
9
|
+
export interface GeminiConfigStatus {
|
|
10
|
+
/** Presence of a project-local `GEMINI.md` in the gateway's cwd. */
|
|
11
|
+
project_gemini_md_present: boolean;
|
|
12
|
+
project_gemini_md_path: string;
|
|
13
|
+
/** Presence of `~/.gemini/GEMINI.md`. */
|
|
14
|
+
user_gemini_md_present: boolean;
|
|
15
|
+
user_gemini_md_path: string;
|
|
16
|
+
/** Presence and contents of `~/.gemini/settings.json` `mcpServers` block. */
|
|
17
|
+
settings_json_present: boolean;
|
|
18
|
+
settings_json_path: string;
|
|
19
|
+
mcp_servers_registered: string[];
|
|
20
|
+
/** Per-server reconciliation against the gateway's `--allowed-mcp-server-names` whitelist. */
|
|
21
|
+
mcp_reconciliation: {
|
|
22
|
+
whitelisted: string[];
|
|
23
|
+
missing_from_settings: string[];
|
|
24
|
+
};
|
|
25
|
+
next_actions: string[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Probe ~/.vibe/config.toml to see whether session_logging is enabled. Vibe
|
|
29
|
+
* persists session logs (which sessionId/--continue depends on) only when
|
|
30
|
+
* `[session_logging] enabled = true` is set. The probe is read-only: the
|
|
31
|
+
* gateway never mutates this file.
|
|
32
|
+
*/
|
|
33
|
+
export declare function checkVibeSessionLogging(home?: string): VibeSessionLoggingStatus;
|
|
34
|
+
/**
|
|
35
|
+
* U27: Probe Gemini's project/user config locations.
|
|
36
|
+
*
|
|
37
|
+
* - `./GEMINI.md` (gateway cwd) and `~/.gemini/GEMINI.md` are documented
|
|
38
|
+
* "context" surfaces. Missing both means Gemini has no project-specific
|
|
39
|
+
* guidance.
|
|
40
|
+
* - `~/.gemini/settings.json` defines registered MCP servers (`mcpServers`
|
|
41
|
+
* block). The gateway tracks its own whitelist (`CLAUDE_MCP_SERVER_NAMES`)
|
|
42
|
+
* and surfaces a reconciliation warning for each whitelisted server not
|
|
43
|
+
* present in settings.json so callers don't ship requests for unregistered
|
|
44
|
+
* servers.
|
|
45
|
+
*/
|
|
46
|
+
export declare function checkGeminiConfig(cwd?: string, home?: string, whitelist?: readonly string[]): GeminiConfigStatus;
|
|
47
|
+
export interface DoctorReport {
|
|
48
|
+
schema_version: "1.0";
|
|
49
|
+
ok: boolean;
|
|
50
|
+
generated_at: string;
|
|
51
|
+
system: {
|
|
52
|
+
os: NodeJS.Platform;
|
|
53
|
+
arch: string;
|
|
54
|
+
release: string;
|
|
55
|
+
node_version: string;
|
|
56
|
+
};
|
|
57
|
+
gateway: {
|
|
58
|
+
name: string;
|
|
59
|
+
version: string;
|
|
60
|
+
};
|
|
61
|
+
transport: {
|
|
62
|
+
default: "stdio" | "http";
|
|
63
|
+
http: {
|
|
64
|
+
enabled: boolean;
|
|
65
|
+
host: string;
|
|
66
|
+
port: number;
|
|
67
|
+
path: string;
|
|
68
|
+
public_url_configured: boolean;
|
|
69
|
+
public_url: string | null;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
auth: {
|
|
73
|
+
required: boolean;
|
|
74
|
+
token_configured: boolean;
|
|
75
|
+
source: string;
|
|
76
|
+
};
|
|
77
|
+
providers: Record<"claude" | "codex" | "gemini" | "grok" | "mistral", {
|
|
78
|
+
cli_available: boolean;
|
|
79
|
+
version: string | null;
|
|
80
|
+
login_status: ProviderLoginStatus;
|
|
81
|
+
version_command: string[];
|
|
82
|
+
login_check: {
|
|
83
|
+
method: "cli" | "credential_store" | "not_checked";
|
|
84
|
+
command: string[] | null;
|
|
85
|
+
credential_store: "present" | "not_found" | "not_checked";
|
|
86
|
+
detail: string;
|
|
87
|
+
};
|
|
88
|
+
install_guidance: {
|
|
89
|
+
summary: string;
|
|
90
|
+
commands: string[];
|
|
91
|
+
documentation_url?: string;
|
|
92
|
+
};
|
|
93
|
+
login_guidance: {
|
|
94
|
+
summary: string;
|
|
95
|
+
commands: string[];
|
|
96
|
+
credential_handling: string;
|
|
97
|
+
};
|
|
98
|
+
}>;
|
|
99
|
+
endpoint_exposure: EndpointExposureReport;
|
|
100
|
+
client_config: {
|
|
101
|
+
claude_desktop_config_present: boolean;
|
|
102
|
+
codex_config_present: boolean;
|
|
103
|
+
gemini_settings_present: boolean;
|
|
104
|
+
gemini_config: GeminiConfigStatus;
|
|
105
|
+
vibe_session_logging: VibeSessionLoggingStatus;
|
|
106
|
+
};
|
|
107
|
+
next_actions: string[];
|
|
108
|
+
}
|
|
109
|
+
export declare function createDoctorReport(env?: NodeJS.ProcessEnv): DoctorReport;
|
|
110
|
+
export declare function printDoctorJson(): void;
|