llm-cli-gateway 1.4.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 +67 -1
- package/README.md +111 -8
- package/dist/approval-manager.d.ts +1 -1
- package/dist/async-job-manager.d.ts +24 -2
- package/dist/async-job-manager.js +71 -7
- package/dist/auth.d.ts +15 -0
- package/dist/auth.js +46 -0
- package/dist/cli-updater.d.ts +19 -2
- package/dist/cli-updater.js +110 -7
- 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 +183 -2
- package/dist/index.js +2629 -1411
- package/dist/logger.d.ts +9 -0
- package/dist/logger.js +14 -0
- package/dist/model-registry.js +40 -6
- 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 +484 -4
- package/dist/request-helpers.js +613 -0
- package/dist/resources.js +44 -0
- package/dist/session-manager-pg.js +1 -0
- package/dist/session-manager.d.ts +1 -1
- package/dist/session-manager.js +2 -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 +15 -5
- package/setup/status.schema.json +271 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parser for Gemini CLI `-o json` output.
|
|
3
|
+
*
|
|
4
|
+
* Gemini emits a single JSON object with:
|
|
5
|
+
* - `response`: string final model output
|
|
6
|
+
* - `usageMetadata`: { promptTokenCount, candidatesTokenCount,
|
|
7
|
+
* cachedContentTokenCount?, totalTokenCount }
|
|
8
|
+
*
|
|
9
|
+
* Returns null when stdout is not parseable as JSON. Returns an object with
|
|
10
|
+
* only `response` when usageMetadata is missing.
|
|
11
|
+
*/
|
|
12
|
+
export function parseGeminiJson(stdout) {
|
|
13
|
+
const trimmed = stdout.trim();
|
|
14
|
+
if (!trimmed) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
let parsed;
|
|
18
|
+
try {
|
|
19
|
+
parsed = JSON.parse(trimmed);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
if (!parsed || typeof parsed !== "object") {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
const result = {};
|
|
28
|
+
if (typeof parsed.response === "string") {
|
|
29
|
+
result.response = parsed.response;
|
|
30
|
+
}
|
|
31
|
+
const meta = parsed.usageMetadata;
|
|
32
|
+
if (meta && typeof meta === "object") {
|
|
33
|
+
const input = typeof meta.promptTokenCount === "number" ? meta.promptTokenCount : undefined;
|
|
34
|
+
const output = typeof meta.candidatesTokenCount === "number" ? meta.candidatesTokenCount : undefined;
|
|
35
|
+
if (input !== undefined || output !== undefined) {
|
|
36
|
+
const usage = {
|
|
37
|
+
input_tokens: input ?? 0,
|
|
38
|
+
output_tokens: output ?? 0,
|
|
39
|
+
};
|
|
40
|
+
if (typeof meta.cachedContentTokenCount === "number") {
|
|
41
|
+
usage.cache_read_tokens = meta.cachedContentTokenCount;
|
|
42
|
+
}
|
|
43
|
+
result.usage = usage;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
package/dist/health.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DatabaseConnection } from "./db.js";
|
|
2
|
+
import { type ProviderRuntimeStatus } from "./provider-status.js";
|
|
2
3
|
export interface HealthStatus {
|
|
3
4
|
status: "healthy" | "degraded" | "unhealthy";
|
|
4
5
|
postgres: {
|
|
@@ -11,6 +12,11 @@ export interface HealthStatus {
|
|
|
11
12
|
};
|
|
12
13
|
timestamp: string;
|
|
13
14
|
}
|
|
15
|
+
export interface ProviderRuntimeHealth {
|
|
16
|
+
status: "healthy" | "degraded" | "unhealthy";
|
|
17
|
+
providers: Record<string, Pick<ProviderRuntimeStatus, "installed" | "version" | "loginStatus" | "loginCheck">>;
|
|
18
|
+
timestamp: string;
|
|
19
|
+
}
|
|
14
20
|
/**
|
|
15
21
|
* Check health status of PostgreSQL and Redis
|
|
16
22
|
* - Both up → healthy
|
|
@@ -18,3 +24,4 @@ export interface HealthStatus {
|
|
|
18
24
|
* - PostgreSQL down → unhealthy (critical failure)
|
|
19
25
|
*/
|
|
20
26
|
export declare function checkHealth(db: DatabaseConnection): Promise<HealthStatus>;
|
|
27
|
+
export declare function checkProviderRuntimeHealth(): ProviderRuntimeHealth;
|
package/dist/health.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { listProviderRuntimeStatuses } from "./provider-status.js";
|
|
1
2
|
/**
|
|
2
3
|
* Check health status of PostgreSQL and Redis
|
|
3
4
|
* - Both up → healthy
|
|
@@ -30,3 +31,24 @@ export async function checkHealth(db) {
|
|
|
30
31
|
}
|
|
31
32
|
return health;
|
|
32
33
|
}
|
|
34
|
+
export function checkProviderRuntimeHealth() {
|
|
35
|
+
const providers = listProviderRuntimeStatuses();
|
|
36
|
+
const projected = Object.fromEntries(Object.entries(providers).map(([name, provider]) => [
|
|
37
|
+
name,
|
|
38
|
+
{
|
|
39
|
+
installed: provider.installed,
|
|
40
|
+
version: provider.version,
|
|
41
|
+
loginStatus: provider.loginStatus,
|
|
42
|
+
loginCheck: provider.loginCheck,
|
|
43
|
+
},
|
|
44
|
+
]));
|
|
45
|
+
const statuses = Object.values(providers);
|
|
46
|
+
const installedCount = statuses.filter(provider => provider.installed).length;
|
|
47
|
+
const authenticatedCount = statuses.filter(provider => provider.loginStatus === "authenticated").length;
|
|
48
|
+
const status = installedCount === 0 ? "unhealthy" : authenticatedCount === 0 ? "degraded" : "healthy";
|
|
49
|
+
return {
|
|
50
|
+
status,
|
|
51
|
+
providers: projected,
|
|
52
|
+
timestamp: new Date().toISOString(),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Server } from "node:http";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import type { GatewayServerDeps } from "./index.js";
|
|
4
|
+
export interface HttpTransportOptions {
|
|
5
|
+
host?: string;
|
|
6
|
+
port?: number;
|
|
7
|
+
path?: string;
|
|
8
|
+
deps?: GatewayServerDeps;
|
|
9
|
+
createGatewayServer: (deps?: GatewayServerDeps) => McpServer;
|
|
10
|
+
logger?: {
|
|
11
|
+
info: (...args: any[]) => void;
|
|
12
|
+
error: (...args: any[]) => void;
|
|
13
|
+
debug: (...args: any[]) => void;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface HttpGatewayHandle {
|
|
17
|
+
server: Server;
|
|
18
|
+
url: string;
|
|
19
|
+
close: () => Promise<void>;
|
|
20
|
+
sessionCount: () => number;
|
|
21
|
+
}
|
|
22
|
+
export declare function startHttpGateway(options: HttpTransportOptions): Promise<HttpGatewayHandle>;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
|
+
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import { authorizeBearerRequest, getRequiredBearerToken, writeAuthFailure } from "./auth.js";
|
|
6
|
+
const noopLogger = {
|
|
7
|
+
info: (..._args) => { },
|
|
8
|
+
error: (..._args) => { },
|
|
9
|
+
debug: (..._args) => { },
|
|
10
|
+
};
|
|
11
|
+
function readBody(req) {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const chunks = [];
|
|
14
|
+
req.on("data", chunk => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
|
15
|
+
req.on("error", reject);
|
|
16
|
+
req.on("end", () => {
|
|
17
|
+
if (chunks.length === 0) {
|
|
18
|
+
resolve(undefined);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const raw = Buffer.concat(chunks).toString("utf8");
|
|
22
|
+
try {
|
|
23
|
+
resolve(JSON.parse(raw));
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
reject(error);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function methodNotAllowed(res) {
|
|
32
|
+
res.writeHead(405, { allow: "GET, POST, DELETE", "content-type": "application/json" });
|
|
33
|
+
res.end(JSON.stringify({ error: "Method not allowed" }));
|
|
34
|
+
}
|
|
35
|
+
function jsonError(res, status, message) {
|
|
36
|
+
res.writeHead(status, { "content-type": "application/json" });
|
|
37
|
+
res.end(JSON.stringify({ error: message }));
|
|
38
|
+
}
|
|
39
|
+
export async function startHttpGateway(options) {
|
|
40
|
+
const host = options.host ?? process.env.LLM_GATEWAY_HTTP_HOST ?? "127.0.0.1";
|
|
41
|
+
const port = options.port ?? Number(process.env.LLM_GATEWAY_HTTP_PORT ?? 3333);
|
|
42
|
+
const path = options.path ?? process.env.LLM_GATEWAY_HTTP_PATH ?? "/mcp";
|
|
43
|
+
const logger = options.logger ?? noopLogger;
|
|
44
|
+
const sessions = new Map();
|
|
45
|
+
const token = getRequiredBearerToken();
|
|
46
|
+
async function closeSession(sessionId) {
|
|
47
|
+
const entry = sessions.get(sessionId);
|
|
48
|
+
if (!entry)
|
|
49
|
+
return;
|
|
50
|
+
sessions.delete(sessionId);
|
|
51
|
+
await entry.transport
|
|
52
|
+
.close()
|
|
53
|
+
.catch(error => logger.error("HTTP transport close failed", error));
|
|
54
|
+
await entry.server.close().catch(error => logger.error("HTTP MCP server close failed", error));
|
|
55
|
+
}
|
|
56
|
+
async function createSession() {
|
|
57
|
+
const gatewayServer = options.createGatewayServer(options.deps);
|
|
58
|
+
const transport = new StreamableHTTPServerTransport({
|
|
59
|
+
sessionIdGenerator: () => randomUUID(),
|
|
60
|
+
onsessioninitialized: sessionId => {
|
|
61
|
+
sessions.set(sessionId, { server: gatewayServer, transport });
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
transport.onclose = () => {
|
|
65
|
+
if (transport.sessionId) {
|
|
66
|
+
sessions.delete(transport.sessionId);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
transport.onerror = error => logger.error("HTTP MCP transport error", error);
|
|
70
|
+
await gatewayServer.connect(transport);
|
|
71
|
+
return { server: gatewayServer, transport };
|
|
72
|
+
}
|
|
73
|
+
const httpServer = createServer(async (req, res) => {
|
|
74
|
+
try {
|
|
75
|
+
const url = new URL(req.url || "/", `http://${req.headers.host || `${host}:${port}`}`);
|
|
76
|
+
if (url.pathname === "/healthz") {
|
|
77
|
+
res.writeHead(200, { "content-type": "application/json" });
|
|
78
|
+
res.end(JSON.stringify({ ok: true, sessions: sessions.size }));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (url.pathname !== path) {
|
|
82
|
+
jsonError(res, 404, "Not found");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const auth = authorizeBearerRequest(req, token);
|
|
86
|
+
if (!auth.ok) {
|
|
87
|
+
writeAuthFailure(res, auth);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (req.method !== "GET" && req.method !== "POST" && req.method !== "DELETE") {
|
|
91
|
+
methodNotAllowed(res);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
95
|
+
const normalizedSessionId = Array.isArray(sessionId) ? sessionId[0] : sessionId;
|
|
96
|
+
if (req.method === "DELETE") {
|
|
97
|
+
if (!normalizedSessionId) {
|
|
98
|
+
jsonError(res, 400, "Missing mcp-session-id");
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
await closeSession(normalizedSessionId);
|
|
102
|
+
res.writeHead(204);
|
|
103
|
+
res.end();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (normalizedSessionId) {
|
|
107
|
+
const entry = sessions.get(normalizedSessionId);
|
|
108
|
+
if (!entry) {
|
|
109
|
+
jsonError(res, 404, "Unknown MCP session");
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const body = req.method === "POST" ? await readBody(req) : undefined;
|
|
113
|
+
await entry.transport.handleRequest(req, res, body);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (req.method !== "POST") {
|
|
117
|
+
if (req.method === "GET") {
|
|
118
|
+
methodNotAllowed(res);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
jsonError(res, 400, "Missing mcp-session-id");
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const body = await readBody(req);
|
|
125
|
+
if (!isInitializeRequest(body)) {
|
|
126
|
+
jsonError(res, 400, "First request must be initialize");
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const entry = await createSession();
|
|
130
|
+
await entry.transport.handleRequest(req, res, body);
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
logger.error("HTTP transport request failed", error);
|
|
134
|
+
if (!res.headersSent) {
|
|
135
|
+
jsonError(res, 500, "Internal server error");
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
res.end();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
await new Promise((resolve, reject) => {
|
|
143
|
+
httpServer.once("error", reject);
|
|
144
|
+
httpServer.listen(port, host, () => {
|
|
145
|
+
httpServer.off("error", reject);
|
|
146
|
+
resolve();
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
const address = httpServer.address();
|
|
150
|
+
const actualPort = typeof address === "object" && address ? address.port : port;
|
|
151
|
+
const url = `http://${host}:${actualPort}${path}`;
|
|
152
|
+
logger.info(`HTTP MCP transport listening at ${url}`);
|
|
153
|
+
return {
|
|
154
|
+
server: httpServer,
|
|
155
|
+
url,
|
|
156
|
+
close: async () => {
|
|
157
|
+
await Promise.all([...sessions.keys()].map(closeSession));
|
|
158
|
+
await new Promise((resolve, reject) => {
|
|
159
|
+
httpServer.close(error => (error ? reject(error) : resolve()));
|
|
160
|
+
});
|
|
161
|
+
},
|
|
162
|
+
sessionCount: () => sessions.size,
|
|
163
|
+
};
|
|
164
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { z } from "zod";
|
|
2
4
|
import { ISessionManager } from "./session-manager.js";
|
|
5
|
+
import { ResourceProvider } from "./resources.js";
|
|
6
|
+
import { PerformanceMetrics } from "./metrics.js";
|
|
7
|
+
import { DatabaseConnection } from "./db.js";
|
|
3
8
|
import { AsyncJobManager } from "./async-job-manager.js";
|
|
4
|
-
import { ApprovalRecord } from "./approval-manager.js";
|
|
9
|
+
import { ApprovalManager, ApprovalRecord } from "./approval-manager.js";
|
|
5
10
|
import { ReviewIntegrityResult } from "./review-integrity.js";
|
|
6
|
-
import { ClaudeMcpServerName } from "./claude-mcp-config.js";
|
|
11
|
+
import { ClaudeMcpConfigResult, ClaudeMcpServerName } from "./claude-mcp-config.js";
|
|
12
|
+
import { type MistralAgentMode, type ClaudePermissionMode, type CodexSandboxMode, type CodexAskForApproval, type ClaudeEffortLevel } from "./request-helpers.js";
|
|
13
|
+
import { FlightRecorderLike } from "./flight-recorder.js";
|
|
7
14
|
type ExtendedToolResponse = {
|
|
8
15
|
content: {
|
|
9
16
|
type: "text";
|
|
@@ -21,6 +28,135 @@ type ExtendedToolResponse = {
|
|
|
21
28
|
};
|
|
22
29
|
reviewIntegrity?: ReviewIntegrityResult;
|
|
23
30
|
};
|
|
31
|
+
declare const logger: {
|
|
32
|
+
info: (message: string, ...args: any[]) => void;
|
|
33
|
+
warn: (message: string, ...args: any[]) => void;
|
|
34
|
+
error: (message: string, ...args: any[]) => void;
|
|
35
|
+
debug: (message: string, ...args: any[]) => void;
|
|
36
|
+
};
|
|
37
|
+
type GatewayLogger = typeof logger;
|
|
38
|
+
export declare const SESSION_PROVIDER_VALUES: readonly ["claude", "codex", "gemini", "grok", "mistral"];
|
|
39
|
+
export declare const SESSION_PROVIDER_ENUM: z.ZodEnum<["claude", "codex", "gemini", "grok", "mistral"]>;
|
|
40
|
+
export type SessionProvider = (typeof SESSION_PROVIDER_VALUES)[number];
|
|
41
|
+
export interface GatewayServerDeps {
|
|
42
|
+
sessionManager?: ISessionManager;
|
|
43
|
+
resourceProvider?: ResourceProvider;
|
|
44
|
+
db?: DatabaseConnection | null;
|
|
45
|
+
performanceMetrics?: PerformanceMetrics;
|
|
46
|
+
asyncJobManager?: AsyncJobManager;
|
|
47
|
+
approvalManager?: ApprovalManager;
|
|
48
|
+
flightRecorder?: FlightRecorderLike;
|
|
49
|
+
logger?: GatewayLogger;
|
|
50
|
+
}
|
|
51
|
+
interface GatewayServerRuntime {
|
|
52
|
+
sessionManager: ISessionManager;
|
|
53
|
+
resourceProvider: ResourceProvider;
|
|
54
|
+
db: DatabaseConnection | null;
|
|
55
|
+
performanceMetrics: PerformanceMetrics;
|
|
56
|
+
asyncJobManager: AsyncJobManager;
|
|
57
|
+
approvalManager: ApprovalManager;
|
|
58
|
+
flightRecorder: FlightRecorderLike;
|
|
59
|
+
logger: GatewayLogger;
|
|
60
|
+
}
|
|
61
|
+
interface CliRequestPrep {
|
|
62
|
+
corrId: string;
|
|
63
|
+
effectivePrompt: string;
|
|
64
|
+
resolvedModel: string | undefined;
|
|
65
|
+
requestedMcpServers: ClaudeMcpServerName[];
|
|
66
|
+
mcpConfig?: ClaudeMcpConfigResult;
|
|
67
|
+
approvalDecision: ApprovalRecord | null;
|
|
68
|
+
reviewIntegrity?: ReviewIntegrityResult;
|
|
69
|
+
args: string[];
|
|
70
|
+
}
|
|
71
|
+
export declare function prepareClaudeRequest(params: {
|
|
72
|
+
prompt: string;
|
|
73
|
+
model?: string;
|
|
74
|
+
outputFormat: "text" | "json" | "stream-json";
|
|
75
|
+
allowedTools?: string[];
|
|
76
|
+
disallowedTools?: string[];
|
|
77
|
+
dangerouslySkipPermissions: boolean;
|
|
78
|
+
permissionMode?: ClaudePermissionMode;
|
|
79
|
+
approvalStrategy: "legacy" | "mcp_managed";
|
|
80
|
+
approvalPolicy?: string;
|
|
81
|
+
mcpServers?: ClaudeMcpServerName[];
|
|
82
|
+
strictMcpConfig: boolean;
|
|
83
|
+
correlationId?: string;
|
|
84
|
+
optimizePrompt: boolean;
|
|
85
|
+
operation: string;
|
|
86
|
+
agent?: string;
|
|
87
|
+
agents?: Record<string, unknown>;
|
|
88
|
+
forkSession?: boolean;
|
|
89
|
+
systemPrompt?: string;
|
|
90
|
+
appendSystemPrompt?: string;
|
|
91
|
+
maxBudgetUsd?: number;
|
|
92
|
+
maxTurns?: number;
|
|
93
|
+
effort?: ClaudeEffortLevel;
|
|
94
|
+
excludeDynamicSystemPromptSections?: boolean;
|
|
95
|
+
}, runtime?: GatewayServerRuntime): CliRequestPrep | ExtendedToolResponse;
|
|
96
|
+
export interface CodexRequestPrep extends CliRequestPrep {
|
|
97
|
+
/**
|
|
98
|
+
* U26: Cleanup hook for any `outputSchema` temp file written during prep.
|
|
99
|
+
* Callers MUST invoke this in a `finally` block (regardless of whether the
|
|
100
|
+
* spawn succeeded, failed, or never ran) to avoid leaking the 0o600 temp
|
|
101
|
+
* file into `os.tmpdir()`.
|
|
102
|
+
*/
|
|
103
|
+
cleanup?: () => void;
|
|
104
|
+
}
|
|
105
|
+
export declare function prepareCodexRequest(params: {
|
|
106
|
+
prompt: string;
|
|
107
|
+
model?: string;
|
|
108
|
+
fullAuto: boolean;
|
|
109
|
+
sandboxMode?: CodexSandboxMode;
|
|
110
|
+
askForApproval?: CodexAskForApproval;
|
|
111
|
+
useLegacyFullAutoFlag?: boolean;
|
|
112
|
+
dangerouslyBypassApprovalsAndSandbox: boolean;
|
|
113
|
+
approvalStrategy: "legacy" | "mcp_managed";
|
|
114
|
+
approvalPolicy?: string;
|
|
115
|
+
mcpServers?: ClaudeMcpServerName[];
|
|
116
|
+
sessionId?: string;
|
|
117
|
+
resumeLatest?: boolean;
|
|
118
|
+
createNewSession?: boolean;
|
|
119
|
+
correlationId?: string;
|
|
120
|
+
optimizePrompt: boolean;
|
|
121
|
+
operation: string;
|
|
122
|
+
/**
|
|
123
|
+
* U23: output format. When set to "json", emits `--json` so Codex streams
|
|
124
|
+
* the JSONL event format that `parseCodexJsonStream` (and downstream
|
|
125
|
+
* `extractUsageAndCost`) can consume. Defaults to "text".
|
|
126
|
+
*/
|
|
127
|
+
outputFormat?: "text" | "json";
|
|
128
|
+
outputSchema?: string | Record<string, unknown>;
|
|
129
|
+
search?: boolean;
|
|
130
|
+
profile?: string;
|
|
131
|
+
configOverrides?: Record<string, string>;
|
|
132
|
+
ephemeral?: boolean;
|
|
133
|
+
images?: string[];
|
|
134
|
+
ignoreUserConfig?: boolean;
|
|
135
|
+
ignoreRules?: boolean;
|
|
136
|
+
}, runtime?: GatewayServerRuntime): CodexRequestPrep | ExtendedToolResponse;
|
|
137
|
+
export declare function prepareGeminiRequest(params: {
|
|
138
|
+
prompt: string;
|
|
139
|
+
model?: string;
|
|
140
|
+
approvalMode?: string;
|
|
141
|
+
approvalStrategy: "legacy" | "mcp_managed";
|
|
142
|
+
approvalPolicy?: string;
|
|
143
|
+
allowedTools?: string[];
|
|
144
|
+
includeDirs?: string[];
|
|
145
|
+
mcpServers?: ClaudeMcpServerName[];
|
|
146
|
+
correlationId?: string;
|
|
147
|
+
optimizePrompt: boolean;
|
|
148
|
+
operation: string;
|
|
149
|
+
/**
|
|
150
|
+
* U23: output format. When set to "json", emits `-o json` so Gemini emits
|
|
151
|
+
* the JSON object containing usageMetadata that `parseGeminiJson` (and
|
|
152
|
+
* downstream `extractUsageAndCost`) can consume. Defaults to "text".
|
|
153
|
+
*/
|
|
154
|
+
outputFormat?: "text" | "json";
|
|
155
|
+
sandbox?: boolean;
|
|
156
|
+
policyFiles?: string[];
|
|
157
|
+
adminPolicyFiles?: string[];
|
|
158
|
+
attachments?: string[];
|
|
159
|
+
}, runtime?: GatewayServerRuntime): CliRequestPrep | ExtendedToolResponse;
|
|
24
160
|
export interface GeminiRequestParams {
|
|
25
161
|
prompt: string;
|
|
26
162
|
model?: string;
|
|
@@ -38,14 +174,22 @@ export interface GeminiRequestParams {
|
|
|
38
174
|
optimizeResponse?: boolean;
|
|
39
175
|
idleTimeoutMs?: number;
|
|
40
176
|
forceRefresh?: boolean;
|
|
177
|
+
/** U23: "json" emits `-o json` so token usage is parsed and reported. */
|
|
178
|
+
outputFormat?: "text" | "json";
|
|
179
|
+
sandbox?: boolean;
|
|
180
|
+
policyFiles?: string[];
|
|
181
|
+
adminPolicyFiles?: string[];
|
|
182
|
+
attachments?: string[];
|
|
41
183
|
}
|
|
42
184
|
export interface HandlerDeps {
|
|
43
185
|
sessionManager: ISessionManager;
|
|
44
186
|
logger: {
|
|
45
187
|
info: (...args: any[]) => void;
|
|
188
|
+
warn?: (...args: any[]) => void;
|
|
46
189
|
error: (...args: any[]) => void;
|
|
47
190
|
debug: (...args: any[]) => void;
|
|
48
191
|
};
|
|
192
|
+
runtime?: GatewayServerRuntime;
|
|
49
193
|
}
|
|
50
194
|
export interface AsyncHandlerDeps extends HandlerDeps {
|
|
51
195
|
asyncJobManager: AsyncJobManager;
|
|
@@ -76,10 +220,36 @@ export interface GrokRequestParams {
|
|
|
76
220
|
}
|
|
77
221
|
export declare function handleGrokRequest(deps: HandlerDeps, params: GrokRequestParams): Promise<ExtendedToolResponse>;
|
|
78
222
|
export declare function handleGrokRequestAsync(deps: AsyncHandlerDeps, params: Omit<GrokRequestParams, "optimizeResponse">): Promise<ExtendedToolResponse>;
|
|
223
|
+
export interface MistralRequestParams {
|
|
224
|
+
prompt: string;
|
|
225
|
+
model?: string;
|
|
226
|
+
outputFormat?: string;
|
|
227
|
+
sessionId?: string;
|
|
228
|
+
resumeLatest: boolean;
|
|
229
|
+
createNewSession: boolean;
|
|
230
|
+
permissionMode?: MistralAgentMode;
|
|
231
|
+
effort?: string;
|
|
232
|
+
reasoningEffort?: string;
|
|
233
|
+
approvalStrategy: "legacy" | "mcp_managed";
|
|
234
|
+
approvalPolicy?: string;
|
|
235
|
+
mcpServers?: ClaudeMcpServerName[];
|
|
236
|
+
allowedTools?: string[];
|
|
237
|
+
disallowedTools?: string[];
|
|
238
|
+
correlationId?: string;
|
|
239
|
+
optimizePrompt: boolean;
|
|
240
|
+
optimizeResponse?: boolean;
|
|
241
|
+
idleTimeoutMs?: number;
|
|
242
|
+
forceRefresh?: boolean;
|
|
243
|
+
}
|
|
244
|
+
export declare function handleMistralRequest(deps: HandlerDeps, params: MistralRequestParams): Promise<ExtendedToolResponse>;
|
|
245
|
+
export declare function handleMistralRequestAsync(deps: AsyncHandlerDeps, params: Omit<MistralRequestParams, "optimizeResponse">): Promise<ExtendedToolResponse>;
|
|
79
246
|
export declare function handleCodexRequestAsync(deps: AsyncHandlerDeps, params: {
|
|
80
247
|
prompt: string;
|
|
81
248
|
model?: string;
|
|
82
249
|
fullAuto: boolean;
|
|
250
|
+
sandboxMode?: CodexSandboxMode;
|
|
251
|
+
askForApproval?: CodexAskForApproval;
|
|
252
|
+
useLegacyFullAutoFlag?: boolean;
|
|
83
253
|
dangerouslyBypassApprovalsAndSandbox: boolean;
|
|
84
254
|
approvalStrategy: "legacy" | "mcp_managed";
|
|
85
255
|
approvalPolicy?: string;
|
|
@@ -91,5 +261,16 @@ export declare function handleCodexRequestAsync(deps: AsyncHandlerDeps, params:
|
|
|
91
261
|
optimizePrompt: boolean;
|
|
92
262
|
idleTimeoutMs?: number;
|
|
93
263
|
forceRefresh?: boolean;
|
|
264
|
+
/** U23: when "json", emits Codex `--json` so the parser is reachable. */
|
|
265
|
+
outputFormat?: "text" | "json";
|
|
266
|
+
outputSchema?: string | Record<string, unknown>;
|
|
267
|
+
search?: boolean;
|
|
268
|
+
profile?: string;
|
|
269
|
+
configOverrides?: Record<string, string>;
|
|
270
|
+
ephemeral?: boolean;
|
|
271
|
+
images?: string[];
|
|
272
|
+
ignoreUserConfig?: boolean;
|
|
273
|
+
ignoreRules?: boolean;
|
|
94
274
|
}): Promise<ExtendedToolResponse>;
|
|
275
|
+
export declare function createGatewayServer(deps?: GatewayServerDeps): McpServer;
|
|
95
276
|
export {};
|