llm-cli-gateway 2.10.0 → 2.11.1
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 +75 -1
- package/README.md +46 -14
- package/dist/acp/event-normalizer.d.ts +42 -0
- package/dist/acp/event-normalizer.js +71 -0
- package/dist/acp/flight-redaction.d.ts +25 -0
- package/dist/acp/flight-redaction.js +40 -0
- package/dist/acp/host-services.d.ts +16 -0
- package/dist/acp/host-services.js +29 -0
- package/dist/acp/permission-bridge.d.ts +15 -0
- package/dist/acp/permission-bridge.js +90 -0
- package/dist/acp/process-manager.js +7 -1
- package/dist/acp/provider-registry.d.ts +1 -1
- package/dist/acp/provider-registry.js +18 -5
- package/dist/acp/runtime.d.ts +35 -0
- package/dist/acp/runtime.js +125 -0
- package/dist/acp/session-map.d.ts +42 -0
- package/dist/acp/session-map.js +67 -0
- package/dist/acp/smoke-harness.d.ts +28 -0
- package/dist/acp/smoke-harness.js +90 -0
- package/dist/api-http.d.ts +18 -0
- package/dist/api-http.js +122 -0
- package/dist/api-provider.d.ts +83 -0
- package/dist/api-provider.js +258 -0
- package/dist/api-request.d.ts +30 -0
- package/dist/api-request.js +51 -0
- package/dist/approval-manager.d.ts +1 -1
- package/dist/approval-manager.js +6 -7
- package/dist/async-job-manager.d.ts +19 -4
- package/dist/async-job-manager.js +211 -35
- package/dist/claude-mcp-config.d.ts +2 -2
- package/dist/claude-mcp-config.js +42 -52
- package/dist/cli-updater.js +16 -1
- package/dist/config.d.ts +20 -0
- package/dist/config.js +93 -35
- package/dist/doctor.d.ts +1 -1
- package/dist/flight-recorder.d.ts +1 -0
- package/dist/flight-recorder.js +11 -0
- package/dist/index.d.ts +56 -5
- package/dist/index.js +639 -38
- package/dist/job-store.d.ts +15 -0
- package/dist/job-store.js +39 -5
- package/dist/mcp-registry.d.ts +17 -0
- package/dist/mcp-registry.js +5 -0
- package/dist/metrics.js +7 -2
- package/dist/model-registry.js +11 -0
- package/dist/prompt-parts.d.ts +6 -6
- package/dist/provider-login-guidance.js +21 -0
- package/dist/provider-status.js +4 -1
- package/dist/provider-tool-capabilities.d.ts +8 -3
- package/dist/provider-tool-capabilities.js +107 -17
- package/dist/request-helpers.d.ts +6 -6
- package/dist/request-helpers.js +1 -4
- package/dist/session-manager-pg.js +2 -9
- package/dist/session-manager.d.ts +9 -4
- package/dist/session-manager.js +13 -4
- package/dist/upstream-contracts.js +184 -24
- package/dist/validation-normalizer.d.ts +2 -2
- package/dist/validation-orchestrator.d.ts +2 -0
- package/dist/validation-orchestrator.js +28 -7
- package/dist/validation-tools.d.ts +61 -0
- package/dist/validation-tools.js +36 -21
- package/migrations/005_provider_type_open_api_names.sql +28 -0
- package/npm-shrinkwrap.json +6 -5
- package/package.json +12 -9
|
@@ -1,7 +1,68 @@
|
|
|
1
|
+
import { z } from "zod/v3";
|
|
1
2
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
3
|
import type { AsyncJobManager } from "./async-job-manager.js";
|
|
3
4
|
import { type ValidationOrchestratorDeps } from "./validation-orchestrator.js";
|
|
4
5
|
export interface ValidationToolDeps extends ValidationOrchestratorDeps {
|
|
5
6
|
asyncJobManager: AsyncJobManager;
|
|
6
7
|
}
|
|
8
|
+
export declare function buildValidationSchemas(deps: ValidationToolDeps): {
|
|
9
|
+
providerSchema: z.ZodEnum<[string, ...string[]]>;
|
|
10
|
+
providerListSchema: z.ZodDefault<z.ZodArray<z.ZodEnum<[string, ...string[]]>, "many">>;
|
|
11
|
+
normalizedProviderResultSchema: z.ZodObject<{
|
|
12
|
+
provider: z.ZodEnum<[string, ...string[]]>;
|
|
13
|
+
model: z.ZodNullable<z.ZodString>;
|
|
14
|
+
status: z.ZodEnum<["running", "completed", "failed", "canceled", "orphaned", "skipped"]>;
|
|
15
|
+
verdict: z.ZodNullable<z.ZodString>;
|
|
16
|
+
rationale: z.ZodNullable<z.ZodString>;
|
|
17
|
+
risks: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
18
|
+
rawJobReference: z.ZodNullable<z.ZodObject<{
|
|
19
|
+
jobId: z.ZodString;
|
|
20
|
+
correlationId: z.ZodString;
|
|
21
|
+
statusTool: z.ZodLiteral<"job_status">;
|
|
22
|
+
resultTool: z.ZodLiteral<"job_result">;
|
|
23
|
+
}, "strip", z.ZodTypeAny, {
|
|
24
|
+
correlationId: string;
|
|
25
|
+
jobId: string;
|
|
26
|
+
statusTool: "job_status";
|
|
27
|
+
resultTool: "job_result";
|
|
28
|
+
}, {
|
|
29
|
+
correlationId: string;
|
|
30
|
+
jobId: string;
|
|
31
|
+
statusTool: "job_status";
|
|
32
|
+
resultTool: "job_result";
|
|
33
|
+
}>>;
|
|
34
|
+
error: z.ZodNullable<z.ZodString>;
|
|
35
|
+
warning: z.ZodOptional<z.ZodString>;
|
|
36
|
+
}, "strip", z.ZodTypeAny, {
|
|
37
|
+
error: string | null;
|
|
38
|
+
status: "running" | "completed" | "failed" | "canceled" | "orphaned" | "skipped";
|
|
39
|
+
model: string | null;
|
|
40
|
+
provider: string;
|
|
41
|
+
rawJobReference: {
|
|
42
|
+
correlationId: string;
|
|
43
|
+
jobId: string;
|
|
44
|
+
statusTool: "job_status";
|
|
45
|
+
resultTool: "job_result";
|
|
46
|
+
} | null;
|
|
47
|
+
verdict: string | null;
|
|
48
|
+
rationale: string | null;
|
|
49
|
+
risks: string[];
|
|
50
|
+
warning?: string | undefined;
|
|
51
|
+
}, {
|
|
52
|
+
error: string | null;
|
|
53
|
+
status: "running" | "completed" | "failed" | "canceled" | "orphaned" | "skipped";
|
|
54
|
+
model: string | null;
|
|
55
|
+
provider: string;
|
|
56
|
+
rawJobReference: {
|
|
57
|
+
correlationId: string;
|
|
58
|
+
jobId: string;
|
|
59
|
+
statusTool: "job_status";
|
|
60
|
+
resultTool: "job_result";
|
|
61
|
+
} | null;
|
|
62
|
+
verdict: string | null;
|
|
63
|
+
rationale: string | null;
|
|
64
|
+
risks?: string[] | undefined;
|
|
65
|
+
warning?: string | undefined;
|
|
66
|
+
}>;
|
|
67
|
+
};
|
|
7
68
|
export declare function registerValidationTools(server: McpServer, deps: ValidationToolDeps): void;
|
package/dist/validation-tools.js
CHANGED
|
@@ -1,26 +1,33 @@
|
|
|
1
1
|
import { z } from "zod/v3";
|
|
2
|
+
import { CLI_TYPES } from "./session-manager.js";
|
|
2
3
|
import { getAvailableCliInfo } from "./model-registry.js";
|
|
4
|
+
import { apiProviderCatalogEntry } from "./api-request.js";
|
|
3
5
|
import { collectValidationJobResult, startJudgeSynthesis, startValidationRun, } from "./validation-orchestrator.js";
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
6
|
+
export function buildValidationSchemas(deps) {
|
|
7
|
+
const apiNames = (deps.apiProviders ?? []).map(p => p.name);
|
|
8
|
+
const allowed = [...CLI_TYPES, ...apiNames];
|
|
9
|
+
const providerSchema = z.enum(allowed);
|
|
10
|
+
const providerListSchema = z.array(providerSchema).min(1).default(["claude", "codex"]);
|
|
11
|
+
const normalizedProviderResultSchema = z.object({
|
|
12
|
+
provider: providerSchema,
|
|
13
|
+
model: z.string().nullable(),
|
|
14
|
+
status: z.enum(["running", "completed", "failed", "canceled", "orphaned", "skipped"]),
|
|
15
|
+
verdict: z.string().nullable(),
|
|
16
|
+
rationale: z.string().nullable(),
|
|
17
|
+
risks: z.array(z.string()).default([]),
|
|
18
|
+
rawJobReference: z
|
|
19
|
+
.object({
|
|
20
|
+
jobId: z.string(),
|
|
21
|
+
correlationId: z.string(),
|
|
22
|
+
statusTool: z.literal("job_status"),
|
|
23
|
+
resultTool: z.literal("job_result"),
|
|
24
|
+
})
|
|
25
|
+
.nullable(),
|
|
26
|
+
error: z.string().nullable(),
|
|
27
|
+
warning: z.string().optional(),
|
|
28
|
+
});
|
|
29
|
+
return { providerSchema, providerListSchema, normalizedProviderResultSchema };
|
|
30
|
+
}
|
|
24
31
|
function textResponse(body) {
|
|
25
32
|
const text = responseText(body);
|
|
26
33
|
return {
|
|
@@ -47,6 +54,7 @@ function findHumanReadableReport(value) {
|
|
|
47
54
|
return null;
|
|
48
55
|
}
|
|
49
56
|
export function registerValidationTools(server, deps) {
|
|
57
|
+
const { providerSchema, providerListSchema, normalizedProviderResultSchema } = buildValidationSchemas(deps);
|
|
50
58
|
server.tool("validate_with_models", "Ask two or more provider CLIs to independently validate a question. Starts validation jobs — poll with job_status, collect with job_result (not llm_job_*).", {
|
|
51
59
|
question: z.string().min(1).describe("Question or content to validate."),
|
|
52
60
|
models: providerListSchema.describe("Providers to ask. Defaults to Claude and Codex."),
|
|
@@ -208,7 +216,14 @@ export function registerValidationTools(server, deps) {
|
|
|
208
216
|
destructiveHint: false,
|
|
209
217
|
idempotentHint: true,
|
|
210
218
|
openWorldHint: false,
|
|
211
|
-
}, async () =>
|
|
219
|
+
}, async () => {
|
|
220
|
+
const apiProviders = (deps.apiProviders ?? []).map(apiProviderCatalogEntry);
|
|
221
|
+
return textResponse({
|
|
222
|
+
success: true,
|
|
223
|
+
models: getAvailableCliInfo(),
|
|
224
|
+
...(apiProviders.length > 0 ? { apiProviders } : {}),
|
|
225
|
+
});
|
|
226
|
+
});
|
|
212
227
|
server.tool("job_status", "Check a VALIDATION job's status (jobs started by validate_with_models/ask_model/etc.) — distinct from llm_job_status, which tracks provider request jobs.", {
|
|
213
228
|
jobId: z.string().min(1).describe("Validation job ID."),
|
|
214
229
|
}, {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-- Slice 0.5 (API-endpoint routing, locked decision B: arbitrary provider names).
|
|
2
|
+
--
|
|
3
|
+
-- Relax the closed provider enum on the session tables so that any
|
|
4
|
+
-- `[providers.<name>]` config key (a kind:"api" provider id) is a valid
|
|
5
|
+
-- `cli` value. Migration 003 widened the constraint only as far as the
|
|
6
|
+
-- hard-coded set ('claude','codex','gemini','grok','mistral','grok-api');
|
|
7
|
+
-- arbitrary API provider names had no DB-level home.
|
|
8
|
+
--
|
|
9
|
+
-- Provider-set validation now lives in the application layer (config loading
|
|
10
|
+
-- plus `SESSION_PROVIDER_ENUM` for the registered set). The database keeps a
|
|
11
|
+
-- single *format* guard so empty strings / whitespace / control characters are
|
|
12
|
+
-- still rejected — it no longer enumerates a fixed provider list. The pattern
|
|
13
|
+
-- accepts the existing five CLIs and `grok-api`, and any well-formed provider
|
|
14
|
+
-- identifier (e.g. `ollama`, `openai`, `vllm`, `llama3.3`).
|
|
15
|
+
|
|
16
|
+
ALTER TABLE sessions DROP CONSTRAINT IF EXISTS sessions_cli_check;
|
|
17
|
+
ALTER TABLE sessions
|
|
18
|
+
ADD CONSTRAINT sessions_cli_check
|
|
19
|
+
CHECK (cli ~ '^[A-Za-z][A-Za-z0-9._-]*$');
|
|
20
|
+
|
|
21
|
+
ALTER TABLE active_sessions DROP CONSTRAINT IF EXISTS active_sessions_cli_check;
|
|
22
|
+
ALTER TABLE active_sessions
|
|
23
|
+
ADD CONSTRAINT active_sessions_cli_check
|
|
24
|
+
CHECK (cli ~ '^[A-Za-z][A-Za-z0-9._-]*$');
|
|
25
|
+
|
|
26
|
+
INSERT INTO schema_migrations (version, name)
|
|
27
|
+
VALUES (5, '005_provider_type_open_api_names')
|
|
28
|
+
ON CONFLICT (version) DO NOTHING;
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llm-cli-gateway",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "llm-cli-gateway",
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.11.1",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
13
|
+
"body-parser": "2.2.2",
|
|
13
14
|
"content-type": "1.0.5",
|
|
14
15
|
"smol-toml": "^1.6.1",
|
|
15
16
|
"type-is": "2.0.1",
|
|
@@ -587,9 +588,9 @@
|
|
|
587
588
|
}
|
|
588
589
|
},
|
|
589
590
|
"node_modules/hono": {
|
|
590
|
-
"version": "4.12.
|
|
591
|
-
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.
|
|
592
|
-
"integrity": "sha512-
|
|
591
|
+
"version": "4.12.25",
|
|
592
|
+
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.25.tgz",
|
|
593
|
+
"integrity": "sha512-2NFaIyNVgJmBs/ecmtGzlmluTFs5cHEWGTdu0t1HBwYzoGXOL5nUQBRMXsXWla5i4KkG//QMzVP88m1+I3fdAQ==",
|
|
593
594
|
"license": "MIT",
|
|
594
595
|
"engines": {
|
|
595
596
|
"node": ">=16.9.0"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llm-cli-gateway",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.1",
|
|
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",
|
|
@@ -88,6 +88,7 @@
|
|
|
88
88
|
},
|
|
89
89
|
"dependencies": {
|
|
90
90
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
91
|
+
"body-parser": "2.2.2",
|
|
91
92
|
"content-type": "1.0.5",
|
|
92
93
|
"smol-toml": "^1.6.1",
|
|
93
94
|
"type-is": "2.0.1",
|
|
@@ -104,24 +105,26 @@
|
|
|
104
105
|
"devDependencies": {
|
|
105
106
|
"@eslint/js": "^10.0.1",
|
|
106
107
|
"@types/better-sqlite3": "^7.6.0",
|
|
107
|
-
"
|
|
108
|
-
"@types/node": "^25.9.1",
|
|
108
|
+
"@types/node": "^25.9.3",
|
|
109
109
|
"@types/pg": "^8.11.10",
|
|
110
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
110
|
+
"@typescript-eslint/eslint-plugin": "^8.61.1",
|
|
111
111
|
"@typescript-eslint/parser": "^8.59.4",
|
|
112
|
-
"@vitest/coverage-v8": "^4.1.
|
|
113
|
-
"
|
|
112
|
+
"@vitest/coverage-v8": "^4.1.9",
|
|
113
|
+
"better-sqlite3": "^12.11.1",
|
|
114
|
+
"eslint": "^10.5.0",
|
|
114
115
|
"eslint-config-prettier": "^10.1.8",
|
|
115
|
-
"eslint-plugin-security": "^4.0.
|
|
116
|
+
"eslint-plugin-security": "^4.0.1",
|
|
116
117
|
"fast-check": "^4.8.0",
|
|
117
118
|
"pg": "^8.12.0",
|
|
118
|
-
"prettier": "^3.
|
|
119
|
+
"prettier": "^3.8.4",
|
|
119
120
|
"typescript": "^6.0.3",
|
|
120
121
|
"vitest": "^4.0.18"
|
|
121
122
|
},
|
|
122
123
|
"overrides": {
|
|
124
|
+
"body-parser": "2.2.2",
|
|
123
125
|
"type-is": "2.0.1",
|
|
124
|
-
"content-type": "1.0.5"
|
|
126
|
+
"content-type": "1.0.5",
|
|
127
|
+
"hono": "^4.12.25"
|
|
125
128
|
},
|
|
126
129
|
"directories": {
|
|
127
130
|
"doc": "docs"
|