llm-cli-gateway 2.11.0 → 2.12.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.
Files changed (36) hide show
  1. package/.agents/skills/async-job-orchestration/SKILL.md +288 -0
  2. package/.agents/skills/implement-review-fix/SKILL.md +154 -0
  3. package/.agents/skills/multi-llm-review/SKILL.md +174 -0
  4. package/.agents/skills/public-demo-session/SKILL.md +100 -0
  5. package/.agents/skills/secure-orchestration/SKILL.md +227 -0
  6. package/.agents/skills/session-workflow/SKILL.md +271 -0
  7. package/CHANGELOG.md +63 -1
  8. package/README.md +86 -27
  9. package/dist/acp/provider-registry.js +6 -6
  10. package/dist/api-provider.d.ts +7 -0
  11. package/dist/api-provider.js +7 -0
  12. package/dist/api-request.js +1 -0
  13. package/dist/async-job-manager.d.ts +11 -1
  14. package/dist/async-job-manager.js +44 -3
  15. package/dist/config.d.ts +2 -0
  16. package/dist/config.js +3 -0
  17. package/dist/index.d.ts +40 -4
  18. package/dist/index.js +611 -158
  19. package/dist/job-store.d.ts +48 -1
  20. package/dist/job-store.js +184 -0
  21. package/dist/provider-codegen.js +3 -0
  22. package/dist/provider-tool-capabilities.d.ts +4 -0
  23. package/dist/provider-tool-capabilities.js +16 -13
  24. package/dist/upstream-contracts.d.ts +1 -0
  25. package/dist/upstream-contracts.js +202 -45
  26. package/dist/validation-orchestrator.d.ts +5 -2
  27. package/dist/validation-orchestrator.js +71 -5
  28. package/dist/validation-receipt.d.ts +68 -0
  29. package/dist/validation-receipt.js +245 -0
  30. package/dist/validation-report.d.ts +4 -2
  31. package/dist/validation-report.js +18 -1
  32. package/dist/validation-tools.js +58 -9
  33. package/npm-shrinkwrap.json +5 -5
  34. package/package.json +10 -4
  35. package/dist/xai-api-provider.d.ts +0 -43
  36. package/dist/xai-api-provider.js +0 -191
@@ -2,12 +2,12 @@ import { randomUUID } from "crypto";
2
2
  import { envWithExtendedPath, getExtendedPath, killProcessGroup, providerCommandName, spawnCliProcess, unregisterProcessGroup, } from "./executor.js";
3
3
  import { noopLogger, logWarn } from "./logger.js";
4
4
  import { ProcessMonitor } from "./process-monitor.js";
5
- import { computeRequestKey } from "./job-store.js";
5
+ import { computeRequestKey, isValidationRunStore } from "./job-store.js";
6
6
  import { NoopFlightRecorder, } from "./flight-recorder.js";
7
7
  import { codexFrResponse } from "./codex-json-parser.js";
8
8
  import { getRequestContext, resolveOwnerPrincipal } from "./request-context.js";
9
9
  import { runApiRequest, ApiHttpError, } from "./api-provider.js";
10
- function extractApiHttpStatus(error) {
10
+ export function extractApiHttpStatus(error) {
11
11
  for (const candidate of [error, error?.cause]) {
12
12
  if (candidate instanceof ApiHttpError && typeof candidate.status === "number") {
13
13
  return candidate.status;
@@ -18,6 +18,14 @@ function extractApiHttpStatus(error) {
18
18
  }
19
19
  return null;
20
20
  }
21
+ export function extractApiErrorBody(error) {
22
+ for (const candidate of [error, error?.cause]) {
23
+ if (candidate instanceof ApiHttpError && candidate.responseText) {
24
+ return candidate.responseText;
25
+ }
26
+ }
27
+ return undefined;
28
+ }
21
29
  const MAX_OUTPUT_SIZE = 50 * 1024 * 1024;
22
30
  const JOB_TTL_MS = 60 * 60 * 1000;
23
31
  const EVICTION_INTERVAL_MS = 5 * 60 * 1000;
@@ -173,6 +181,9 @@ export class AsyncJobManager {
173
181
  hasStore() {
174
182
  return this.store !== null;
175
183
  }
184
+ getValidationRunStore() {
185
+ return this.store && isValidationRunStore(this.store) ? this.store : null;
186
+ }
176
187
  emitMetrics(job) {
177
188
  if (job.metricsRecorded)
178
189
  return;
@@ -404,6 +415,9 @@ export class AsyncJobManager {
404
415
  job.stdout = result.text;
405
416
  job.httpStatus = result.httpStatus;
406
417
  job.exitCode = 0;
418
+ job.apiUsage = result.usage;
419
+ job.apiResponseId = result.responseId ?? null;
420
+ job.apiModel = result.model;
407
421
  }
408
422
  else {
409
423
  job.status = "failed";
@@ -413,6 +427,7 @@ export class AsyncJobManager {
413
427
  job.stderr = message;
414
428
  job.error = message;
415
429
  job.exitCode = 1;
430
+ job.apiErrorBody = extractApiErrorBody(error);
416
431
  }
417
432
  job.finishedAt = new Date().toISOString();
418
433
  job.exited = true;
@@ -443,7 +458,13 @@ export class AsyncJobManager {
443
458
  if (job.flightRecorderComplete)
444
459
  return;
445
460
  const durationMs = Math.max(0, Date.now() - new Date(job.startedAt).getTime());
446
- const usage = finalStatus === "completed" && job.extractUsage ? this.safeExtractUsage(job) : {};
461
+ const usage = finalStatus !== "completed"
462
+ ? {}
463
+ : job.transport === "http"
464
+ ? this.httpUsage(job)
465
+ : job.extractUsage
466
+ ? this.safeExtractUsage(job)
467
+ : {};
447
468
  const isFailure = finalStatus === "failed";
448
469
  let response;
449
470
  if (job.transport === "process" && job.cli === "codex") {
@@ -491,6 +512,17 @@ export class AsyncJobManager {
491
512
  return {};
492
513
  }
493
514
  }
515
+ httpUsage(job) {
516
+ const u = job.apiUsage;
517
+ if (!u)
518
+ return {};
519
+ return {
520
+ inputTokens: u.inputTokens,
521
+ outputTokens: u.outputTokens,
522
+ cacheReadTokens: u.cacheReadTokens,
523
+ costUsd: u.costUsd,
524
+ };
525
+ }
494
526
  armFlightCompleteForDeferral(jobId) {
495
527
  const job = this.jobs.get(jobId);
496
528
  if (!job)
@@ -846,6 +878,15 @@ export class AsyncJobManager {
846
878
  stderr: stderr.text,
847
879
  stdoutTruncated: stdout.truncated,
848
880
  stderrTruncated: stderr.truncated,
881
+ ...(job.transport === "http"
882
+ ? {
883
+ apiUsage: job.apiUsage,
884
+ httpStatus: job.httpStatus,
885
+ responseId: job.apiResponseId,
886
+ model: job.apiModel,
887
+ errorBody: job.apiErrorBody,
888
+ }
889
+ : {}),
849
890
  };
850
891
  }
851
892
  cancelJob(jobId) {
package/dist/config.d.ts CHANGED
@@ -76,6 +76,7 @@ export interface ApiProviderConfig {
76
76
  baseUrl: string;
77
77
  defaultModel: string;
78
78
  models?: string[];
79
+ usageInclude?: boolean;
79
80
  }
80
81
  export interface ApiProviderRuntime {
81
82
  name: string;
@@ -83,6 +84,7 @@ export interface ApiProviderRuntime {
83
84
  baseUrl: string;
84
85
  defaultModel: string;
85
86
  models?: string[];
87
+ usageInclude?: boolean;
86
88
  apiKey: string;
87
89
  }
88
90
  export interface ProvidersConfig {
package/dist/config.js CHANGED
@@ -301,6 +301,7 @@ const ApiProviderSchema = z
301
301
  api_key_env: z.string().min(1).optional(),
302
302
  default_model: z.string().min(1),
303
303
  models: z.array(z.string().min(1)).nonempty().optional(),
304
+ usage_include: z.boolean().optional(),
304
305
  })
305
306
  .strict();
306
307
  function readProvidersFile(configPath, logger) {
@@ -369,6 +370,7 @@ export function loadProvidersConfig(logger = noopLogger) {
369
370
  baseUrl: parsed.data.base_url,
370
371
  defaultModel: parsed.data.default_model,
371
372
  models: parsed.data.models ? [...parsed.data.models] : undefined,
373
+ usageInclude: parsed.data.usage_include,
372
374
  };
373
375
  }
374
376
  return { xai, providers, sources: { configFile: sourcePath } };
@@ -395,6 +397,7 @@ export function enabledApiProviders(config, env = process.env) {
395
397
  baseUrl: provider.baseUrl,
396
398
  defaultModel: provider.defaultModel,
397
399
  models: provider.models,
400
+ usageInclude: provider.usageInclude,
398
401
  apiKey: resolveProviderKey(provider.apiKeyEnv, env) ?? "",
399
402
  });
400
403
  }
package/dist/index.d.ts CHANGED
@@ -5,7 +5,6 @@ import { ISessionManager, type CliType, type ProviderType } from "./session-mana
5
5
  import { ResourceProvider } from "./resources.js";
6
6
  import { PerformanceMetrics } from "./metrics.js";
7
7
  import { type PersistenceConfig, type CacheAwarenessConfig, type ProvidersConfig, type ApiProviderRuntime, type AcpConfig } from "./config.js";
8
- import { type XaiReasoningEffort } from "./xai-api-provider.js";
9
8
  import { DatabaseConnection } from "./db.js";
10
9
  import { AsyncJobManager } from "./async-job-manager.js";
11
10
  import { ApprovalManager, ApprovalRecord } from "./approval-manager.js";
@@ -63,6 +62,7 @@ export declare const WORKTREE_SCHEMA: z.ZodUnion<[z.ZodBoolean, z.ZodObject<{
63
62
  export declare const WORKSPACE_ALIAS_SCHEMA: z.ZodString;
64
63
  export declare const SESSION_PROVIDER_VALUES: readonly ["claude", "codex", "gemini", "grok", "mistral", "devin", "grok-api"];
65
64
  export declare const SESSION_PROVIDER_ENUM: z.ZodEnum<["claude", "codex", "gemini", "grok", "mistral", "devin", "grok-api"]>;
65
+ export declare function sessionProviderValuesFor(providers: ProvidersConfig): string[];
66
66
  export type SessionProvider = ProviderType;
67
67
  export interface GatewayServerDeps {
68
68
  sessionManager?: ISessionManager;
@@ -120,6 +120,25 @@ export declare function resolveWorktreeForRequest(worktreeOpt: boolean | {
120
120
  workspaceRoot?: string;
121
121
  }): Promise<ResolvedWorktree>;
122
122
  export declare function formatWorktreePrefix(worktreePath?: string): string;
123
+ export declare function createErrorResponse(cli: string, code: number, stderr: string, correlationId?: string, error?: Error, apiError?: {
124
+ httpStatus?: number | null;
125
+ responseBody?: string;
126
+ }): {
127
+ content: {
128
+ type: "text";
129
+ text: string;
130
+ }[];
131
+ isError: boolean;
132
+ structuredContent: {
133
+ httpStatus?: number | undefined;
134
+ responseBody?: string | undefined;
135
+ response: string;
136
+ correlationId: string | null;
137
+ cli: string;
138
+ exitCode: number;
139
+ errorCategory: string;
140
+ };
141
+ };
123
142
  export declare function extractUsageAndCost(cli: "claude" | "codex" | "gemini" | "grok" | "mistral" | "devin", output: string, outputFormat?: string, ctx?: {
124
143
  sessionId?: string;
125
144
  home?: string;
@@ -232,6 +251,8 @@ export declare function prepareGeminiRequest(params: {
232
251
  attachments?: string[];
233
252
  skipTrust?: boolean;
234
253
  yolo?: boolean;
254
+ project?: string;
255
+ newProject?: boolean;
235
256
  }, runtime?: GatewayServerRuntime): CliRequestPrep | ExtendedToolResponse;
236
257
  export declare function prepareGrokRequest(params: {
237
258
  prompt?: string;
@@ -278,6 +299,9 @@ export declare function prepareGrokRequest(params: {
278
299
  restoreCode?: boolean;
279
300
  leaderSocket?: string;
280
301
  nativeWorktree?: boolean | string;
302
+ worktreeRef?: string;
303
+ forkSession?: boolean;
304
+ jsonSchema?: string | Record<string, unknown>;
281
305
  }, runtime?: GatewayServerRuntime): CliRequestPrep | ExtendedToolResponse;
282
306
  export declare function prepareMistralRequest(params: {
283
307
  prompt?: string;
@@ -309,6 +333,7 @@ export declare function buildMistralRetryPrep(params: Pick<MistralRequestParams,
309
333
  env: Record<string, string>;
310
334
  ignoredDisallowedTools: boolean;
311
335
  };
336
+ export declare function buildCliResponse(cli: "claude" | "codex" | "gemini" | "grok" | "mistral" | "devin", stdout: string, optimizeResponse: boolean, corrId: string, sessionId: string | undefined, prep: CliRequestPrep, durationMs: number, resumable?: boolean, outputFormat?: string, warnings?: WarningEntry[]): ExtendedToolResponse;
312
337
  export interface GrokApiRequestParams {
313
338
  prompt?: string;
314
339
  promptParts?: PromptParts;
@@ -321,12 +346,13 @@ export interface GrokApiRequestParams {
321
346
  maxOutputTokens?: number;
322
347
  temperature?: number;
323
348
  topP?: number;
324
- reasoningEffort?: XaiReasoningEffort;
349
+ reasoningEffort?: "none" | "low" | "medium" | "high";
325
350
  timeoutMs?: number;
326
351
  }
327
352
  export declare function handleGrokApiRequest(deps: HandlerDeps, params: GrokApiRequestParams): Promise<ExtendedToolResponse>;
328
353
  interface ApiProviderToolParams {
329
354
  prompt?: string;
355
+ promptParts?: PromptParts;
330
356
  system?: string;
331
357
  model?: string;
332
358
  correlationId?: string;
@@ -335,6 +361,11 @@ interface ApiProviderToolParams {
335
361
  topP?: number;
336
362
  reasoningEffort?: "none" | "low" | "medium" | "high";
337
363
  timeoutMs?: number;
364
+ optimizePrompt?: boolean;
365
+ optimizeResponse?: boolean;
366
+ forceRefresh?: boolean;
367
+ sessionId?: string;
368
+ createNewSession?: boolean;
338
369
  }
339
370
  export declare function handleApiProviderRequest(runtimeArg: GatewayServerRuntime, providerRuntime: ApiProviderRuntime, params: ApiProviderToolParams): Promise<ExtendedToolResponse>;
340
371
  export declare function handleApiProviderRequestAsync(runtimeArg: GatewayServerRuntime, providerRuntime: ApiProviderRuntime, params: ApiProviderToolParams): ExtendedToolResponse;
@@ -364,6 +395,8 @@ export interface GeminiRequestParams {
364
395
  attachments?: string[];
365
396
  skipTrust?: boolean;
366
397
  yolo?: boolean;
398
+ project?: string;
399
+ newProject?: boolean;
367
400
  workspace?: string;
368
401
  worktree?: boolean | {
369
402
  name?: string;
@@ -437,6 +470,9 @@ export interface GrokRequestParams {
437
470
  restoreCode?: boolean;
438
471
  leaderSocket?: string;
439
472
  nativeWorktree?: boolean | string;
473
+ worktreeRef?: string;
474
+ forkSession?: boolean;
475
+ jsonSchema?: string | Record<string, unknown>;
440
476
  workspace?: string;
441
477
  worktree?: boolean | {
442
478
  name?: string;
@@ -448,7 +484,7 @@ export declare function handleGrokRequestAsync(deps: AsyncHandlerDeps, params: O
448
484
  export interface DevinRequestParams {
449
485
  prompt?: string;
450
486
  model?: string;
451
- permissionMode?: "normal" | "auto" | "dangerous" | "yolo" | "bypass";
487
+ permissionMode?: "auto" | "smart" | "dangerous";
452
488
  promptFile?: string;
453
489
  transport?: "cli" | "acp";
454
490
  sessionId?: string;
@@ -463,7 +499,7 @@ export interface DevinRequestParams {
463
499
  export declare function prepareDevinRequest(params: {
464
500
  prompt?: string;
465
501
  model?: string;
466
- permissionMode?: string;
502
+ permissionMode?: DevinRequestParams["permissionMode"];
467
503
  promptFile?: string;
468
504
  correlationId?: string;
469
505
  optimizePrompt: boolean;