llm-cli-gateway 1.5.33 → 1.5.35
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 +12 -0
- package/dist/index.js +76 -20
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the llm-cli-gateway project.
|
|
4
4
|
|
|
5
|
+
## [1.5.35] - 2026-05-25
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Keep metadata-only CLI commands quiet by avoiding flight-recorder and job-persistence startup before `--version`, help, `doctor --json`, and `contracts --json`; machine-readable JSON commands now emit JSON without startup log lines.
|
|
10
|
+
|
|
11
|
+
## [1.5.34] - 2026-05-25
|
|
12
|
+
|
|
13
|
+
### Security
|
|
14
|
+
|
|
15
|
+
- Pin the development Redis client fixture back to `ioredis@5.9.2` and reject the Socket-flagged `ioredis@5.10.1` / `@ioredis/commands@1.5.1` lockfile pair in the release security audit. The runtime Redis integration remains an optional peer dependency.
|
|
16
|
+
|
|
5
17
|
## [1.5.33] - 2026-05-25
|
|
6
18
|
|
|
7
19
|
### Security
|
package/dist/index.js
CHANGED
|
@@ -108,6 +108,22 @@ const SYNC_DEADLINE_MS = (() => {
|
|
|
108
108
|
const __filename = fileURLToPath(import.meta.url);
|
|
109
109
|
const __dirname = dirname(__filename);
|
|
110
110
|
const SKILLS_DIR = join(__dirname, "..", ".agents", "skills");
|
|
111
|
+
function packageVersion() {
|
|
112
|
+
const candidates = [
|
|
113
|
+
join(__dirname, "..", "package.json"),
|
|
114
|
+
join(__dirname, "..", "..", "package.json"),
|
|
115
|
+
];
|
|
116
|
+
for (const candidate of candidates) {
|
|
117
|
+
try {
|
|
118
|
+
const parsed = JSON.parse(readFileSync(candidate, "utf8"));
|
|
119
|
+
return parsed.version || "unknown";
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// Try next candidate.
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return "unknown";
|
|
126
|
+
}
|
|
111
127
|
function loadSkills() {
|
|
112
128
|
const skills = [];
|
|
113
129
|
try {
|
|
@@ -158,29 +174,51 @@ let sessionManager;
|
|
|
158
174
|
let db = null;
|
|
159
175
|
const performanceMetrics = new PerformanceMetrics();
|
|
160
176
|
let resourceProvider;
|
|
161
|
-
|
|
177
|
+
let flightRecorder = null;
|
|
162
178
|
// Resolved persistence config — single source of truth for the async-job backend.
|
|
163
179
|
// Driven by ~/.llm-cli-gateway/config.toml (+ deprecated env-var overrides).
|
|
164
180
|
// When backend = "none", the JobStore is null AND *_request_async tools are not
|
|
165
181
|
// registered (see createGatewayServer), making silent in-memory loss
|
|
166
182
|
// structurally impossible.
|
|
167
|
-
|
|
168
|
-
|
|
183
|
+
let persistenceConfig = null;
|
|
184
|
+
let jobStore = null;
|
|
185
|
+
let jobStoreInitialized = false;
|
|
186
|
+
let asyncJobManager = null;
|
|
187
|
+
let approvalManager = null;
|
|
188
|
+
function getFlightRecorder(runtimeLogger = logger) {
|
|
189
|
+
flightRecorder ??= createFlightRecorder(runtimeLogger);
|
|
190
|
+
return flightRecorder;
|
|
191
|
+
}
|
|
192
|
+
function getPersistenceConfig(runtimeLogger = logger) {
|
|
193
|
+
persistenceConfig ??= loadPersistenceConfig(runtimeLogger);
|
|
194
|
+
return persistenceConfig;
|
|
195
|
+
}
|
|
196
|
+
function getJobStore(runtimeLogger = logger) {
|
|
197
|
+
if (jobStoreInitialized)
|
|
198
|
+
return jobStore;
|
|
199
|
+
jobStoreInitialized = true;
|
|
169
200
|
try {
|
|
170
|
-
|
|
201
|
+
jobStore = createJobStore(getPersistenceConfig(runtimeLogger), runtimeLogger);
|
|
171
202
|
}
|
|
172
203
|
catch (err) {
|
|
173
|
-
|
|
174
|
-
|
|
204
|
+
runtimeLogger.error("Failed to open durable job store; async tools will be unavailable", err);
|
|
205
|
+
jobStore = null;
|
|
175
206
|
}
|
|
176
|
-
|
|
177
|
-
|
|
207
|
+
return jobStore;
|
|
208
|
+
}
|
|
209
|
+
function newAsyncJobManager(metrics, runtimeLogger, store = getJobStore(runtimeLogger)) {
|
|
178
210
|
return new AsyncJobManager(runtimeLogger, (cli, durationMs, success) => {
|
|
179
211
|
metrics.recordRequest(cli, durationMs, success);
|
|
180
212
|
}, store);
|
|
181
213
|
}
|
|
182
|
-
|
|
183
|
-
|
|
214
|
+
function getAsyncJobManager(runtimeLogger = logger) {
|
|
215
|
+
asyncJobManager ??= newAsyncJobManager(performanceMetrics, runtimeLogger);
|
|
216
|
+
return asyncJobManager;
|
|
217
|
+
}
|
|
218
|
+
function getApprovalManager(runtimeLogger = logger) {
|
|
219
|
+
approvalManager ??= new ApprovalManager(undefined, runtimeLogger);
|
|
220
|
+
return approvalManager;
|
|
221
|
+
}
|
|
184
222
|
const MCP_SERVER_ENUM = z.enum(CLAUDE_MCP_SERVER_NAMES);
|
|
185
223
|
// U22: Session-provider enum extended to five providers. The storage layer's
|
|
186
224
|
// CLI_TYPES already includes "mistral"; the MCP-tool layer mirrors that here so
|
|
@@ -199,9 +237,11 @@ function resolveGatewayServerRuntime(deps = {}, options = {}) {
|
|
|
199
237
|
? // Factory-created test/HTTP session servers must not mark another instance's
|
|
200
238
|
// durable jobs orphaned. Stdio startup injects the process-global manager.
|
|
201
239
|
newAsyncJobManager(runtimePerformanceMetrics, runtimeLogger, null)
|
|
202
|
-
:
|
|
240
|
+
: getAsyncJobManager(runtimeLogger));
|
|
203
241
|
const runtimeApprovalManager = deps.approvalManager ??
|
|
204
|
-
(options.isolateState
|
|
242
|
+
(options.isolateState
|
|
243
|
+
? new ApprovalManager(undefined, runtimeLogger)
|
|
244
|
+
: getApprovalManager(runtimeLogger));
|
|
205
245
|
return {
|
|
206
246
|
sessionManager: runtimeSessionManager,
|
|
207
247
|
resourceProvider: deps.resourceProvider ??
|
|
@@ -212,9 +252,9 @@ function resolveGatewayServerRuntime(deps = {}, options = {}) {
|
|
|
212
252
|
performanceMetrics: runtimePerformanceMetrics,
|
|
213
253
|
asyncJobManager: runtimeAsyncJobManager,
|
|
214
254
|
approvalManager: runtimeApprovalManager,
|
|
215
|
-
flightRecorder: deps.flightRecorder ??
|
|
255
|
+
flightRecorder: deps.flightRecorder ?? getFlightRecorder(runtimeLogger),
|
|
216
256
|
logger: runtimeLogger,
|
|
217
|
-
persistence: deps.persistence ??
|
|
257
|
+
persistence: deps.persistence ?? getPersistenceConfig(runtimeLogger),
|
|
218
258
|
};
|
|
219
259
|
}
|
|
220
260
|
// Per-CLI idle timeouts: kill process if no stdout/stderr activity for this duration.
|
|
@@ -3944,7 +3984,7 @@ function registerHealthResource(server) {
|
|
|
3944
3984
|
description: "Async job health (CPU, memory, zombie detection)",
|
|
3945
3985
|
mimeType: "application/json",
|
|
3946
3986
|
}, async (uri) => {
|
|
3947
|
-
const health =
|
|
3987
|
+
const health = getAsyncJobManager().getJobHealth();
|
|
3948
3988
|
return {
|
|
3949
3989
|
contents: [
|
|
3950
3990
|
{
|
|
@@ -3980,8 +4020,10 @@ async function shutdown(signal) {
|
|
|
3980
4020
|
await db.disconnect();
|
|
3981
4021
|
logger.info("Database connections closed");
|
|
3982
4022
|
}
|
|
3983
|
-
flightRecorder
|
|
3984
|
-
|
|
4023
|
+
if (flightRecorder) {
|
|
4024
|
+
flightRecorder.close();
|
|
4025
|
+
logger.info("Flight recorder closed");
|
|
4026
|
+
}
|
|
3985
4027
|
process.exit(0);
|
|
3986
4028
|
}
|
|
3987
4029
|
catch (error) {
|
|
@@ -3997,6 +4039,20 @@ process.on("SIGINT", () => shutdown("SIGINT"));
|
|
|
3997
4039
|
async function main() {
|
|
3998
4040
|
startWindowsBootstrapperSelfHeal();
|
|
3999
4041
|
const args = process.argv.slice(2);
|
|
4042
|
+
if (args[0] === "--version" || args[0] === "-version" || args[0] === "version") {
|
|
4043
|
+
process.stdout.write(`${packageVersion()}\n`);
|
|
4044
|
+
return;
|
|
4045
|
+
}
|
|
4046
|
+
if (args[0] === "--help" || args[0] === "-help" || args[0] === "/?" || args[0] === "help") {
|
|
4047
|
+
process.stdout.write([
|
|
4048
|
+
"llm-cli-gateway MCP server",
|
|
4049
|
+
"",
|
|
4050
|
+
"Usage:",
|
|
4051
|
+
" llm-cli-gateway [doctor --json|contracts --json|--transport=http|--version]",
|
|
4052
|
+
"",
|
|
4053
|
+
].join("\n"));
|
|
4054
|
+
return;
|
|
4055
|
+
}
|
|
4000
4056
|
if (args[0] === "doctor") {
|
|
4001
4057
|
if (args.includes("--json")) {
|
|
4002
4058
|
printDoctorJson();
|
|
@@ -4035,9 +4091,9 @@ async function main() {
|
|
|
4035
4091
|
resourceProvider,
|
|
4036
4092
|
db,
|
|
4037
4093
|
performanceMetrics,
|
|
4038
|
-
asyncJobManager,
|
|
4039
|
-
approvalManager,
|
|
4040
|
-
flightRecorder,
|
|
4094
|
+
asyncJobManager: getAsyncJobManager(logger),
|
|
4095
|
+
approvalManager: getApprovalManager(logger),
|
|
4096
|
+
flightRecorder: getFlightRecorder(logger),
|
|
4041
4097
|
logger,
|
|
4042
4098
|
};
|
|
4043
4099
|
if (transportMode === "http") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llm-cli-gateway",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.35",
|
|
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",
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
"@vitest/coverage-v8": "^4.1.2",
|
|
110
110
|
"eslint": "^8.57.1",
|
|
111
111
|
"eslint-config-prettier": "^9.0.0",
|
|
112
|
-
"ioredis": "
|
|
112
|
+
"ioredis": "5.9.2",
|
|
113
113
|
"pg": "^8.12.0",
|
|
114
114
|
"prettier": "^3.0.0",
|
|
115
115
|
"typescript": "^5.0.0",
|