llm-cli-gateway 2.3.0 → 2.5.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 +79 -9
- package/README.md +3 -1
- package/dist/auth.d.ts +44 -1
- package/dist/auth.js +60 -13
- package/dist/config.d.ts +19 -0
- package/dist/config.js +235 -0
- package/dist/doctor.d.ts +15 -0
- package/dist/doctor.js +22 -11
- package/dist/executor.js +17 -21
- package/dist/flight-recorder.d.ts +2 -1
- package/dist/http-transport.js +74 -12
- package/dist/index.d.ts +42 -7
- package/dist/index.js +1161 -82
- package/dist/metrics.d.ts +3 -3
- package/dist/metrics.js +8 -8
- package/dist/oauth.d.ts +38 -0
- package/dist/oauth.js +441 -0
- package/dist/request-context.d.ts +7 -0
- package/dist/request-context.js +8 -0
- package/dist/request-helpers.d.ts +8 -8
- package/dist/resources.js +56 -7
- package/dist/session-manager-pg.d.ts +6 -6
- package/dist/session-manager-pg.js +1 -0
- package/dist/session-manager.d.ts +16 -12
- package/dist/session-manager.js +4 -1
- package/dist/upstream-contracts.d.ts +84 -0
- package/dist/upstream-contracts.js +714 -6
- package/dist/workspace-registry.d.ts +63 -0
- package/dist/workspace-registry.js +417 -0
- package/dist/xai-api-provider.d.ts +43 -0
- package/dist/xai-api-provider.js +191 -0
- package/migrations/001_initial_schema.sql +65 -0
- package/migrations/002_session_ids_as_text.sql +26 -0
- package/migrations/003_provider_type_sessions.sql +20 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -1
- package/setup/status.schema.json +42 -1
package/dist/resources.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { CLI_TYPES, PROVIDER_TYPES } from "./session-manager.js";
|
|
1
2
|
import { getAvailableCliInfo } from "./model-registry.js";
|
|
2
3
|
import { computeGlobalCacheStats, computePrefixCacheStats, computeSessionCacheStats, computeTtlRemaining, } from "./cache-stats.js";
|
|
4
|
+
import { buildProviderSubcommandsCompactCatalog, getCliSubcommandContract, serializeCliSubcommandContract, } from "./upstream-contracts.js";
|
|
3
5
|
export class ResourceProvider {
|
|
4
6
|
sessionManager;
|
|
5
7
|
performanceMetrics;
|
|
@@ -163,11 +165,26 @@ export class ResourceProvider {
|
|
|
163
165
|
priority: 0.9,
|
|
164
166
|
},
|
|
165
167
|
},
|
|
168
|
+
{
|
|
169
|
+
uri: "provider-subcommands://catalog",
|
|
170
|
+
name: "Provider Subcommands Catalog",
|
|
171
|
+
title: "Provider Subcommands Catalog",
|
|
172
|
+
description: "Compact read-only catalog of declared provider CLI subcommands",
|
|
173
|
+
mimeType: "application/json",
|
|
174
|
+
annotations: {
|
|
175
|
+
audience: ["user", "assistant"],
|
|
176
|
+
priority: 0.7,
|
|
177
|
+
},
|
|
178
|
+
},
|
|
166
179
|
];
|
|
167
180
|
}
|
|
168
181
|
async readResource(uri) {
|
|
169
182
|
if (uri === "sessions://all") {
|
|
170
183
|
const sessions = await this.sessionManager.listSessions();
|
|
184
|
+
const activeSessions = Object.fromEntries(await Promise.all(PROVIDER_TYPES.map(async (provider) => [
|
|
185
|
+
provider,
|
|
186
|
+
(await this.sessionManager.getActiveSession(provider))?.id || null,
|
|
187
|
+
])));
|
|
171
188
|
return {
|
|
172
189
|
uri,
|
|
173
190
|
mimeType: "application/json",
|
|
@@ -180,13 +197,7 @@ export class ResourceProvider {
|
|
|
180
197
|
createdAt: s.createdAt,
|
|
181
198
|
lastUsedAt: s.lastUsedAt,
|
|
182
199
|
})),
|
|
183
|
-
activeSessions
|
|
184
|
-
claude: (await this.sessionManager.getActiveSession("claude"))?.id || null,
|
|
185
|
-
codex: (await this.sessionManager.getActiveSession("codex"))?.id || null,
|
|
186
|
-
gemini: (await this.sessionManager.getActiveSession("gemini"))?.id || null,
|
|
187
|
-
grok: (await this.sessionManager.getActiveSession("grok"))?.id || null,
|
|
188
|
-
mistral: (await this.sessionManager.getActiveSession("mistral"))?.id || null,
|
|
189
|
-
},
|
|
200
|
+
activeSessions,
|
|
190
201
|
}, null, 2),
|
|
191
202
|
};
|
|
192
203
|
}
|
|
@@ -302,6 +313,44 @@ export class ResourceProvider {
|
|
|
302
313
|
text: JSON.stringify(this.performanceMetrics.snapshot(), null, 2),
|
|
303
314
|
};
|
|
304
315
|
}
|
|
316
|
+
if (uri === "provider-subcommands://catalog" || uri === "provider_subcommands://catalog") {
|
|
317
|
+
return {
|
|
318
|
+
uri,
|
|
319
|
+
mimeType: "application/json",
|
|
320
|
+
text: JSON.stringify(buildProviderSubcommandsCompactCatalog()),
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
const subcommandResource = parseProviderSubcommandUri(uri);
|
|
324
|
+
if (subcommandResource) {
|
|
325
|
+
const contract = getCliSubcommandContract(subcommandResource.provider, subcommandResource.commandPath);
|
|
326
|
+
if (!contract)
|
|
327
|
+
return null;
|
|
328
|
+
return {
|
|
329
|
+
uri,
|
|
330
|
+
mimeType: "application/json",
|
|
331
|
+
text: JSON.stringify({
|
|
332
|
+
schemaVersion: "provider-subcommand-contract.v1",
|
|
333
|
+
contract: serializeCliSubcommandContract(subcommandResource.provider, contract),
|
|
334
|
+
}, null, 2),
|
|
335
|
+
};
|
|
336
|
+
}
|
|
305
337
|
return null;
|
|
306
338
|
}
|
|
307
339
|
}
|
|
340
|
+
function parseProviderSubcommandUri(uri) {
|
|
341
|
+
const prefix = uri.startsWith("provider-subcommands://")
|
|
342
|
+
? "provider-subcommands://"
|
|
343
|
+
: uri.startsWith("provider_subcommands://")
|
|
344
|
+
? "provider_subcommands://"
|
|
345
|
+
: null;
|
|
346
|
+
if (!prefix || uri === `${prefix}catalog`)
|
|
347
|
+
return null;
|
|
348
|
+
const rest = uri.slice(prefix.length);
|
|
349
|
+
const [providerRaw, ...pathParts] = rest.split("/");
|
|
350
|
+
if (!CLI_TYPES.includes(providerRaw) || pathParts.length === 0)
|
|
351
|
+
return null;
|
|
352
|
+
return {
|
|
353
|
+
provider: providerRaw,
|
|
354
|
+
commandPath: pathParts.map(part => decodeURIComponent(part)).filter(Boolean),
|
|
355
|
+
};
|
|
356
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import type { Pool } from "pg";
|
|
2
|
-
import { Session,
|
|
2
|
+
import { Session, ProviderType } from "./session-manager.js";
|
|
3
3
|
export type { Logger } from "./logger.js";
|
|
4
4
|
export declare class PostgreSQLSessionManager {
|
|
5
5
|
private pool;
|
|
6
6
|
constructor(pool: Pool);
|
|
7
|
-
createSession(cli:
|
|
7
|
+
createSession(cli: ProviderType, description?: string, sessionId?: string): Promise<Session>;
|
|
8
8
|
getSession(sessionId: string): Promise<Session | null>;
|
|
9
|
-
listSessions(cli?:
|
|
9
|
+
listSessions(cli?: ProviderType): Promise<Session[]>;
|
|
10
10
|
deleteSession(sessionId: string): Promise<boolean>;
|
|
11
|
-
setActiveSession(cli:
|
|
12
|
-
getActiveSession(cli:
|
|
11
|
+
setActiveSession(cli: ProviderType, sessionId: string | null): Promise<boolean>;
|
|
12
|
+
getActiveSession(cli: ProviderType): Promise<Session | null>;
|
|
13
13
|
updateSessionUsage(sessionId: string): Promise<void>;
|
|
14
14
|
updateSessionMetadata(sessionId: string, metadata: Record<string, any>): Promise<boolean>;
|
|
15
|
-
clearAllSessions(cli?:
|
|
15
|
+
clearAllSessions(cli?: ProviderType): Promise<number>;
|
|
16
16
|
}
|
|
@@ -3,9 +3,13 @@ import type { DatabaseConnection } from "./db.js";
|
|
|
3
3
|
import type { Logger } from "./logger.js";
|
|
4
4
|
export declare const CLI_TYPES: readonly ["claude", "codex", "gemini", "grok", "mistral"];
|
|
5
5
|
export type CliType = (typeof CLI_TYPES)[number];
|
|
6
|
+
export declare const API_PROVIDER_TYPES: readonly ["grok-api"];
|
|
7
|
+
export type ApiProviderType = (typeof API_PROVIDER_TYPES)[number];
|
|
8
|
+
export declare const PROVIDER_TYPES: readonly ["claude", "codex", "gemini", "grok", "mistral", "grok-api"];
|
|
9
|
+
export type ProviderType = (typeof PROVIDER_TYPES)[number];
|
|
6
10
|
export interface Session {
|
|
7
11
|
id: string;
|
|
8
|
-
cli:
|
|
12
|
+
cli: ProviderType;
|
|
9
13
|
createdAt: string;
|
|
10
14
|
lastUsedAt: string;
|
|
11
15
|
description?: string;
|
|
@@ -13,7 +17,7 @@ export interface Session {
|
|
|
13
17
|
}
|
|
14
18
|
export interface SessionStorage {
|
|
15
19
|
sessions: Record<string, Session>;
|
|
16
|
-
activeSession: Record<
|
|
20
|
+
activeSession: Record<ProviderType, string | null>;
|
|
17
21
|
}
|
|
18
22
|
export type SessionCleanupHook = (session: Session) => void | Promise<void>;
|
|
19
23
|
export declare class FileSessionManager {
|
|
@@ -32,27 +36,27 @@ export declare class FileSessionManager {
|
|
|
32
36
|
private ensureStorageDirectory;
|
|
33
37
|
private loadStorage;
|
|
34
38
|
private saveStorage;
|
|
35
|
-
createSession(cli:
|
|
39
|
+
createSession(cli: ProviderType, description?: string, sessionId?: string): Session;
|
|
36
40
|
getSession(sessionId: string): Session | null;
|
|
37
|
-
listSessions(cli?:
|
|
41
|
+
listSessions(cli?: ProviderType): Session[];
|
|
38
42
|
deleteSession(sessionId: string): boolean;
|
|
39
|
-
setActiveSession(cli:
|
|
40
|
-
getActiveSession(cli:
|
|
43
|
+
setActiveSession(cli: ProviderType, sessionId: string | null): boolean;
|
|
44
|
+
getActiveSession(cli: ProviderType): Session | null;
|
|
41
45
|
updateSessionUsage(sessionId: string): void;
|
|
42
46
|
updateSessionMetadata(sessionId: string, metadata: Record<string, any>): boolean;
|
|
43
|
-
clearAllSessions(cli?:
|
|
47
|
+
clearAllSessions(cli?: ProviderType): number;
|
|
44
48
|
}
|
|
45
49
|
export declare const SessionManager: typeof FileSessionManager;
|
|
46
50
|
export interface ISessionManager {
|
|
47
|
-
createSession(cli:
|
|
51
|
+
createSession(cli: ProviderType, description?: string, sessionId?: string): Session | Promise<Session>;
|
|
48
52
|
getSession(sessionId: string): Session | null | Promise<Session | null>;
|
|
49
|
-
listSessions(cli?:
|
|
53
|
+
listSessions(cli?: ProviderType): Session[] | Promise<Session[]>;
|
|
50
54
|
deleteSession(sessionId: string): boolean | Promise<boolean>;
|
|
51
|
-
setActiveSession(cli:
|
|
52
|
-
getActiveSession(cli:
|
|
55
|
+
setActiveSession(cli: ProviderType, sessionId: string | null): boolean | Promise<boolean>;
|
|
56
|
+
getActiveSession(cli: ProviderType): Session | null | Promise<Session | null>;
|
|
53
57
|
updateSessionUsage(sessionId: string): void | Promise<void>;
|
|
54
58
|
updateSessionMetadata(sessionId: string, metadata: Record<string, any>): boolean | Promise<boolean>;
|
|
55
|
-
clearAllSessions(cli?:
|
|
59
|
+
clearAllSessions(cli?: ProviderType): number | Promise<number>;
|
|
56
60
|
}
|
|
57
61
|
export declare function createSessionManager(config?: Config, db?: DatabaseConnection, logger?: Logger, opts?: {
|
|
58
62
|
cleanupHook?: SessionCleanupHook;
|
package/dist/session-manager.js
CHANGED
|
@@ -5,13 +5,16 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync, openSyn
|
|
|
5
5
|
import { DEFAULT_SESSION_TTL_SECONDS } from "./config.js";
|
|
6
6
|
import { noopLogger } from "./logger.js";
|
|
7
7
|
export const CLI_TYPES = ["claude", "codex", "gemini", "grok", "mistral"];
|
|
8
|
-
const
|
|
8
|
+
export const API_PROVIDER_TYPES = ["grok-api"];
|
|
9
|
+
export const PROVIDER_TYPES = [...CLI_TYPES, ...API_PROVIDER_TYPES];
|
|
10
|
+
const createEmptyActiveSessions = () => Object.fromEntries(PROVIDER_TYPES.map(provider => [provider, null]));
|
|
9
11
|
const DEFAULT_SESSION_DESCRIPTIONS = {
|
|
10
12
|
claude: "Claude Session",
|
|
11
13
|
codex: "Codex Session",
|
|
12
14
|
gemini: "Gemini Session",
|
|
13
15
|
grok: "Grok Session",
|
|
14
16
|
mistral: "Mistral Session",
|
|
17
|
+
"grok-api": "Grok API Session",
|
|
15
18
|
};
|
|
16
19
|
export class FileSessionManager {
|
|
17
20
|
storagePath;
|
|
@@ -21,6 +21,7 @@ export interface CliContract {
|
|
|
21
21
|
upstream: string;
|
|
22
22
|
helpArgs: string[][];
|
|
23
23
|
flags: Record<string, CliFlagContract>;
|
|
24
|
+
subcommands?: Record<string, CliSubcommandContract>;
|
|
24
25
|
env?: Record<string, CliFlagContract>;
|
|
25
26
|
mcpTools: readonly string[];
|
|
26
27
|
mcpParameters: readonly string[];
|
|
@@ -43,6 +44,25 @@ export interface CliContractFixture {
|
|
|
43
44
|
env?: Record<string, string>;
|
|
44
45
|
expect: "pass" | "fail";
|
|
45
46
|
}
|
|
47
|
+
export type CliSubcommandRisk = "read_only" | "writes_local_config" | "auth" | "network" | "starts_server" | "updates_binary" | "destructive" | "executes_agent";
|
|
48
|
+
export type CliSubcommandExposure = "tracked_only" | "mcp_readonly" | "mcp_requires_approval" | "not_exposed";
|
|
49
|
+
export type CliSubcommandTier = "catalog" | "inspect" | "execute_candidate" | "diagnostic";
|
|
50
|
+
export type CliSubcommandTokenCost = "tiny" | "small" | "medium" | "large";
|
|
51
|
+
export interface CliSubcommandContract {
|
|
52
|
+
commandPath: readonly string[];
|
|
53
|
+
helpArgs: readonly string[][];
|
|
54
|
+
flags: Record<string, CliFlagContract>;
|
|
55
|
+
maxPositionals: number;
|
|
56
|
+
acknowledgedUpstreamFlags?: readonly string[];
|
|
57
|
+
aliases?: readonly string[];
|
|
58
|
+
children?: Record<string, CliSubcommandContract>;
|
|
59
|
+
risk: CliSubcommandRisk;
|
|
60
|
+
exposure: CliSubcommandExposure;
|
|
61
|
+
tier: CliSubcommandTier;
|
|
62
|
+
tokenCost: CliSubcommandTokenCost;
|
|
63
|
+
summary: string;
|
|
64
|
+
conformanceFixtures: readonly CliContractFixture[];
|
|
65
|
+
}
|
|
46
66
|
export interface ContractViolation {
|
|
47
67
|
cli: CliType;
|
|
48
68
|
arg?: string;
|
|
@@ -53,9 +73,55 @@ export interface ContractValidationResult {
|
|
|
53
73
|
ok: boolean;
|
|
54
74
|
violations: ContractViolation[];
|
|
55
75
|
}
|
|
76
|
+
export interface SubcommandContractValidationResult extends ContractValidationResult {
|
|
77
|
+
commandPath: readonly string[];
|
|
78
|
+
risk?: CliSubcommandRisk;
|
|
79
|
+
exposure?: CliSubcommandExposure;
|
|
80
|
+
tier?: CliSubcommandTier;
|
|
81
|
+
}
|
|
82
|
+
export interface ProviderSubcommandCatalogRow {
|
|
83
|
+
provider: CliType;
|
|
84
|
+
commandPath: readonly string[];
|
|
85
|
+
aliases: readonly string[];
|
|
86
|
+
tier: CliSubcommandTier;
|
|
87
|
+
risk: CliSubcommandRisk;
|
|
88
|
+
exposure: CliSubcommandExposure;
|
|
89
|
+
tokenCost: CliSubcommandTokenCost;
|
|
90
|
+
summary: string;
|
|
91
|
+
driftStatus: "unknown" | "clean" | "drift";
|
|
92
|
+
resourceUri: string;
|
|
93
|
+
}
|
|
94
|
+
export interface ProviderSubcommandCompactCatalog {
|
|
95
|
+
schemaVersion: "provider-subcommands-catalog.v1";
|
|
96
|
+
columns: readonly [
|
|
97
|
+
"provider",
|
|
98
|
+
"commandPath",
|
|
99
|
+
"aliases",
|
|
100
|
+
"tier",
|
|
101
|
+
"risk",
|
|
102
|
+
"exposure",
|
|
103
|
+
"tokenCost",
|
|
104
|
+
"summary",
|
|
105
|
+
"driftStatus",
|
|
106
|
+
"resourceUri"
|
|
107
|
+
];
|
|
108
|
+
rows: readonly (readonly string[])[];
|
|
109
|
+
}
|
|
56
110
|
export declare const UPSTREAM_CLI_CONTRACTS: Record<CliType, CliContract>;
|
|
57
111
|
export declare function validateUpstreamCliArgs(cli: CliType, args: readonly string[]): ContractValidationResult;
|
|
58
112
|
export declare function assertUpstreamCliArgs(cli: CliType, args: readonly string[]): void;
|
|
113
|
+
export declare function flattenCliSubcommands(subcommands: Record<string, CliSubcommandContract> | undefined): CliSubcommandContract[];
|
|
114
|
+
export declare function getCliSubcommandContract(cli: CliType, commandPath: readonly string[]): CliSubcommandContract | null;
|
|
115
|
+
export declare function serializeCliSubcommandContract(cli: CliType, contract: CliSubcommandContract): Record<string, unknown>;
|
|
116
|
+
export declare function listProviderSubcommands(options?: {
|
|
117
|
+
provider?: CliType;
|
|
118
|
+
tier?: CliSubcommandTier;
|
|
119
|
+
risk?: CliSubcommandRisk;
|
|
120
|
+
exposure?: CliSubcommandExposure;
|
|
121
|
+
commandPathPrefix?: readonly string[];
|
|
122
|
+
}): ProviderSubcommandCatalogRow[];
|
|
123
|
+
export declare function buildProviderSubcommandsCompactCatalog(options?: Parameters<typeof listProviderSubcommands>[0]): ProviderSubcommandCompactCatalog;
|
|
124
|
+
export declare function validateUpstreamCliSubcommandArgs(cli: CliType, commandPath: readonly string[], args: readonly string[]): SubcommandContractValidationResult;
|
|
59
125
|
export declare function validateUpstreamCliEnv(cli: CliType, env: Record<string, string> | undefined): ContractValidationResult;
|
|
60
126
|
export declare function assertUpstreamCliEnv(cli: CliType, env: Record<string, string> | undefined): void;
|
|
61
127
|
export declare function extractDiscoveredFlags(helpText: string): readonly string[];
|
|
@@ -66,6 +132,23 @@ export interface FlagDriftResult {
|
|
|
66
132
|
warnings: string[];
|
|
67
133
|
}
|
|
68
134
|
export declare function computeFlagDrift(contract: CliContract, helpText: string, discoveredFlags: readonly string[]): FlagDriftResult;
|
|
135
|
+
export declare function computeSubcommandFlagDrift(contract: CliSubcommandContract, executable: string, helpText: string, discoveredFlags: readonly string[]): FlagDriftResult;
|
|
136
|
+
export interface InstalledCliSubcommandProbe {
|
|
137
|
+
commandPath: readonly string[];
|
|
138
|
+
checkedHelpCommands: string[][];
|
|
139
|
+
available: boolean;
|
|
140
|
+
missingFlags: string[];
|
|
141
|
+
extraFlags: readonly string[];
|
|
142
|
+
acknowledgedExtraFlags: readonly string[];
|
|
143
|
+
discoveredFlags: readonly string[];
|
|
144
|
+
helpHash?: string;
|
|
145
|
+
probedAt: string;
|
|
146
|
+
warnings: string[];
|
|
147
|
+
risk: CliSubcommandRisk;
|
|
148
|
+
exposure: CliSubcommandExposure;
|
|
149
|
+
tier: CliSubcommandTier;
|
|
150
|
+
summary: string;
|
|
151
|
+
}
|
|
69
152
|
export interface InstalledCliContractProbe {
|
|
70
153
|
cli: CliType;
|
|
71
154
|
executable: string;
|
|
@@ -79,6 +162,7 @@ export interface InstalledCliContractProbe {
|
|
|
79
162
|
discoveredFlags: readonly string[];
|
|
80
163
|
helpHash?: string;
|
|
81
164
|
versionHint?: string;
|
|
165
|
+
subcommands: Record<string, InstalledCliSubcommandProbe>;
|
|
82
166
|
probedAt: string;
|
|
83
167
|
warnings: string[];
|
|
84
168
|
}
|