llm-cli-gateway 1.0.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/CHANGELOG.md +541 -0
- package/LICENSE +21 -0
- package/README.md +545 -0
- package/dist/approval-manager.d.ts +43 -0
- package/dist/approval-manager.js +156 -0
- package/dist/async-job-manager.d.ts +57 -0
- package/dist/async-job-manager.js +334 -0
- package/dist/claude-mcp-config.d.ts +8 -0
- package/dist/claude-mcp-config.js +161 -0
- package/dist/config.d.ts +35 -0
- package/dist/config.js +56 -0
- package/dist/db.d.ts +48 -0
- package/dist/db.js +170 -0
- package/dist/executor.d.ts +30 -0
- package/dist/executor.js +315 -0
- package/dist/health.d.ts +20 -0
- package/dist/health.js +32 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.js +1503 -0
- package/dist/logger.d.ts +6 -0
- package/dist/logger.js +5 -0
- package/dist/metrics.d.ts +23 -0
- package/dist/metrics.js +57 -0
- package/dist/migrate-sessions.d.ts +12 -0
- package/dist/migrate-sessions.js +145 -0
- package/dist/migrate.d.ts +2 -0
- package/dist/migrate.js +100 -0
- package/dist/model-registry.d.ts +10 -0
- package/dist/model-registry.js +346 -0
- package/dist/optimizer.d.ts +3 -0
- package/dist/optimizer.js +183 -0
- package/dist/process-monitor.d.ts +54 -0
- package/dist/process-monitor.js +146 -0
- package/dist/request-helpers.d.ts +25 -0
- package/dist/request-helpers.js +32 -0
- package/dist/resources.d.ts +26 -0
- package/dist/resources.js +201 -0
- package/dist/retry.d.ts +72 -0
- package/dist/retry.js +146 -0
- package/dist/review-integrity.d.ts +50 -0
- package/dist/review-integrity.js +283 -0
- package/dist/session-manager-pg.d.ts +76 -0
- package/dist/session-manager-pg.js +383 -0
- package/dist/session-manager.d.ts +62 -0
- package/dist/session-manager.js +223 -0
- package/dist/stream-json-parser.d.ts +35 -0
- package/dist/stream-json-parser.js +94 -0
- package/package.json +90 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NDJSON parser for Claude `--output-format stream-json --include-partial-messages`.
|
|
3
|
+
*
|
|
4
|
+
* Each line of stdout is a complete JSON object. This parser extracts the
|
|
5
|
+
* final result text, cost, usage, and metadata from the stream.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Parse completed NDJSON stdout from `claude --output-format stream-json --include-partial-messages`.
|
|
9
|
+
*
|
|
10
|
+
* Parsing strategy:
|
|
11
|
+
* 1. Split by newlines, filter empty lines
|
|
12
|
+
* 2. JSON.parse each line, skip malformed lines
|
|
13
|
+
* 3. Find the `type=result` event — contains final text, cost, usage
|
|
14
|
+
* 4. Fall back to the last `type=assistant` event if no result event
|
|
15
|
+
* 5. Extract `model` from `type=system` (init) event
|
|
16
|
+
*
|
|
17
|
+
* No rawEvents stored — the stdout buffer is already in memory.
|
|
18
|
+
*/
|
|
19
|
+
export function parseStreamJson(stdout) {
|
|
20
|
+
const lines = stdout.split("\n").filter(line => line.trim().length > 0);
|
|
21
|
+
let resultEvent = null;
|
|
22
|
+
let assistantEvent = null;
|
|
23
|
+
let systemEvent = null;
|
|
24
|
+
for (const line of lines) {
|
|
25
|
+
let parsed;
|
|
26
|
+
try {
|
|
27
|
+
parsed = JSON.parse(line);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Skip malformed lines
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (parsed.type === "result") {
|
|
34
|
+
resultEvent = parsed;
|
|
35
|
+
}
|
|
36
|
+
else if (parsed.type === "assistant") {
|
|
37
|
+
assistantEvent = parsed;
|
|
38
|
+
}
|
|
39
|
+
else if (parsed.type === "system" && parsed.subtype === "init") {
|
|
40
|
+
systemEvent = parsed;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Extract from result event (preferred)
|
|
44
|
+
if (resultEvent) {
|
|
45
|
+
const usage = resultEvent.usage ? {
|
|
46
|
+
inputTokens: resultEvent.usage.input_tokens ?? 0,
|
|
47
|
+
outputTokens: resultEvent.usage.output_tokens ?? 0,
|
|
48
|
+
cacheReadInputTokens: resultEvent.usage.cache_read_input_tokens ?? 0,
|
|
49
|
+
cacheCreationInputTokens: resultEvent.usage.cache_creation_input_tokens ?? 0,
|
|
50
|
+
} : null;
|
|
51
|
+
return {
|
|
52
|
+
text: resultEvent.result ?? "",
|
|
53
|
+
costUsd: resultEvent.total_cost_usd ?? null,
|
|
54
|
+
usage,
|
|
55
|
+
sessionId: resultEvent.session_id ?? systemEvent?.session_id ?? null,
|
|
56
|
+
model: systemEvent?.model ?? resultEvent.model ?? null,
|
|
57
|
+
durationApiMs: resultEvent.duration_api_ms ?? null,
|
|
58
|
+
isError: resultEvent.is_error === true,
|
|
59
|
+
numTurns: resultEvent.num_turns ?? null,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// Fallback: extract text from assistant event
|
|
63
|
+
if (assistantEvent) {
|
|
64
|
+
const message = assistantEvent.message;
|
|
65
|
+
let text = "";
|
|
66
|
+
if (message?.content && Array.isArray(message.content)) {
|
|
67
|
+
text = message.content
|
|
68
|
+
.filter((block) => block.type === "text")
|
|
69
|
+
.map((block) => block.text)
|
|
70
|
+
.join("");
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
text,
|
|
74
|
+
costUsd: null,
|
|
75
|
+
usage: null,
|
|
76
|
+
sessionId: systemEvent?.session_id ?? null,
|
|
77
|
+
model: systemEvent?.model ?? message?.model ?? null,
|
|
78
|
+
durationApiMs: null,
|
|
79
|
+
isError: false,
|
|
80
|
+
numTurns: null,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// No result or assistant event found — return empty
|
|
84
|
+
return {
|
|
85
|
+
text: "",
|
|
86
|
+
costUsd: null,
|
|
87
|
+
usage: null,
|
|
88
|
+
sessionId: systemEvent?.session_id ?? null,
|
|
89
|
+
model: systemEvent?.model ?? null,
|
|
90
|
+
durationApiMs: null,
|
|
91
|
+
isError: false,
|
|
92
|
+
numTurns: null,
|
|
93
|
+
};
|
|
94
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "llm-cli-gateway",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server providing unified access to Claude Code, Codex, and Gemini CLIs with session management, retry logic, and async job orchestration.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "VerivusAI Labs",
|
|
8
|
+
"url": "https://github.com/verivus-oss"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/verivus-oss/llm-cli-gateway.git"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/verivus-oss/llm-cli-gateway#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/verivus-oss/llm-cli-gateway/issues"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"mcp",
|
|
20
|
+
"llm",
|
|
21
|
+
"claude",
|
|
22
|
+
"codex",
|
|
23
|
+
"gemini",
|
|
24
|
+
"orchestration",
|
|
25
|
+
"model-context-protocol",
|
|
26
|
+
"ai",
|
|
27
|
+
"cli-gateway"
|
|
28
|
+
],
|
|
29
|
+
"type": "module",
|
|
30
|
+
"main": "dist/index.js",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"default": "./dist/index.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"bin": {
|
|
38
|
+
"llm-cli-gateway": "./dist/index.js"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=18.0.0"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist/**/*.js",
|
|
45
|
+
"dist/**/*.d.ts",
|
|
46
|
+
"!dist/__tests__/**",
|
|
47
|
+
"README.md",
|
|
48
|
+
"CHANGELOG.md",
|
|
49
|
+
"LICENSE"
|
|
50
|
+
],
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsc -p tsconfig.build.json",
|
|
53
|
+
"build:all": "tsc",
|
|
54
|
+
"prepublishOnly": "npm run build && npm test",
|
|
55
|
+
"start": "node dist/index.js",
|
|
56
|
+
"migrate": "node dist/migrate.js",
|
|
57
|
+
"test": "vitest run",
|
|
58
|
+
"test:coverage": "vitest run --coverage",
|
|
59
|
+
"test:watch": "vitest",
|
|
60
|
+
"test:unit": "vitest run src/__tests__/executor.test.ts",
|
|
61
|
+
"test:session": "vitest run src/__tests__/session-manager.test.ts",
|
|
62
|
+
"test:session-pg": "bash ./scripts/test-pg.sh src/__tests__/session-manager-pg.test.ts",
|
|
63
|
+
"test:integration": "vitest run src/__tests__/integration.test.ts",
|
|
64
|
+
"test:pg": "bash ./scripts/test-pg.sh",
|
|
65
|
+
"test:all": "npm run test && npm run test:pg",
|
|
66
|
+
"lint": "eslint src/**/*.ts",
|
|
67
|
+
"lint:fix": "eslint src/**/*.ts --fix",
|
|
68
|
+
"format": "prettier --write 'src/**/*.ts'",
|
|
69
|
+
"format:check": "prettier --check 'src/**/*.ts'",
|
|
70
|
+
"check": "npm run build && npm run lint && npm test"
|
|
71
|
+
},
|
|
72
|
+
"dependencies": {
|
|
73
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
74
|
+
"ioredis": "^5.4.1",
|
|
75
|
+
"pg": "^8.12.0",
|
|
76
|
+
"toml": "^3.0.0",
|
|
77
|
+
"zod": "^3.23.0"
|
|
78
|
+
},
|
|
79
|
+
"devDependencies": {
|
|
80
|
+
"@types/node": "^20.19.30",
|
|
81
|
+
"@types/pg": "^8.11.10",
|
|
82
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
83
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
84
|
+
"eslint": "^8.0.0",
|
|
85
|
+
"eslint-config-prettier": "^9.0.0",
|
|
86
|
+
"prettier": "^3.0.0",
|
|
87
|
+
"typescript": "^5.0.0",
|
|
88
|
+
"vitest": "^4.0.18"
|
|
89
|
+
}
|
|
90
|
+
}
|