llm-cli-gateway 1.17.3 → 1.17.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 CHANGED
@@ -4,6 +4,36 @@ All notable changes to the llm-cli-gateway project.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## [1.17.4] - 2026-06-02: upstream contract compatibility
8
+
9
+ Patch release that realigns the provider CLI contracts with the currently
10
+ installed binaries (codex 0.135.0, grok 0.2.16, gemini 0.44.1, claude 2.1.159,
11
+ vibe 2.12.1).
12
+
13
+ ### Fixed
14
+
15
+ - Mistral: dropped the unsupported `--effort` / `--reasoning-effort` surface.
16
+ vibe 2.x argparse rejects both flags, so any `mistral_request` that passed
17
+ `effort` / `reasoningEffort` failed before reaching the model. Locked out with
18
+ two `expect:fail` conformance fixtures and a builder guard test.
19
+
20
+ ### Added
21
+
22
+ - Grok: `--compaction-mode` (summary|transcript|segments) and
23
+ `--compaction-detail` (none|minimal|balanced|verbose) context controls, wired
24
+ as enum passthrough flags on `grok_request` / `grok_request_async`.
25
+ - Gemini: a `yolo` boolean that emits `--yolo` (auto-approve all actions). It
26
+ routes through the mcp_managed approval gate and is never emitted alongside
27
+ `--approval-mode yolo`.
28
+ - Claude: `--no-session-persistence`, `--setting-sources`, `--settings`, and
29
+ `--tools` exposed through `prepareClaudeHighImpactFlags`. `--betas` is left
30
+ out on purpose, since it is API-key only and the gateway runs Claude via OAuth.
31
+
32
+ ### Notes
33
+
34
+ - Documented `--max-turns` as a known `--probe-installed` false-positive: claude
35
+ 2.x hides it from `--help` but still accepts it.
36
+
7
37
  ## [1.17.3] - 2026-05-31 — Socket scanner prose cleanup
8
38
 
9
39
  Patch release that removes wording in shipped metadata that Socket classified
package/dist/index.d.ts CHANGED
@@ -264,6 +264,10 @@ export declare function prepareClaudeRequest(params: {
264
264
  fallbackModel?: string;
265
265
  jsonSchema?: string | Record<string, unknown>;
266
266
  addDir?: string[];
267
+ noSessionPersistence?: boolean;
268
+ settingSources?: string;
269
+ settings?: string;
270
+ tools?: string[];
267
271
  }, runtime?: GatewayServerRuntime): CliRequestPrep | ExtendedToolResponse;
268
272
  export interface CodexRequestPrep extends CliRequestPrep {
269
273
  /**
@@ -340,6 +344,14 @@ export declare function prepareGeminiRequest(params: {
340
344
  * is undefined (preserves current prompt behaviour for legacy callers).
341
345
  */
342
346
  skipTrust?: boolean;
347
+ /**
348
+ * Emit `--yolo` (auto-approve all actions). Equivalent in effect to
349
+ * `approvalMode: "yolo"`; provided for CLI ergonomic parity. Routed
350
+ * through the same approval gate (sets `bypassRequested`), and never
351
+ * emitted alongside `--approval-mode yolo` so there is a single
352
+ * auto-approve path. Default undefined.
353
+ */
354
+ yolo?: boolean;
343
355
  }, runtime?: GatewayServerRuntime): CliRequestPrep | ExtendedToolResponse;
344
356
  export declare function prepareGrokRequest(params: {
345
357
  prompt?: string;
@@ -388,6 +400,16 @@ export declare function prepareGrokRequest(params: {
388
400
  systemPromptOverride?: string;
389
401
  allow?: string[];
390
402
  deny?: string[];
403
+ /**
404
+ * Grok 0.2.x context/compaction controls (both enum passthrough flags):
405
+ * - `compactionMode` → `--compaction-mode <summary|transcript|segments>`
406
+ * (default summary; sets GROK_COMPACTION_MODE).
407
+ * - `compactionDetail` → `--compaction-detail <none|minimal|balanced|verbose>`
408
+ * (default verbose; only affects `--compaction-mode segments`; sets
409
+ * GROK_COMPACTION_DETAIL).
410
+ */
411
+ compactionMode?: string;
412
+ compactionDetail?: string;
391
413
  }, runtime?: GatewayServerRuntime): CliRequestPrep | ExtendedToolResponse;
392
414
  export declare function prepareMistralRequest(params: {
393
415
  prompt?: string;
@@ -395,8 +417,6 @@ export declare function prepareMistralRequest(params: {
395
417
  model?: string;
396
418
  outputFormat?: string;
397
419
  permissionMode?: MistralAgentMode;
398
- effort?: string;
399
- reasoningEffort?: string;
400
420
  allowedTools?: string[];
401
421
  disallowedTools?: string[];
402
422
  approvalStrategy: "legacy" | "mcp_managed";
@@ -432,7 +452,7 @@ export declare function prepareMistralRequest(params: {
432
452
  * through here, or a fresh-workspace / budgeted run can degrade on
433
453
  * the second attempt.
434
454
  */
435
- export declare function buildMistralRetryPrep(params: Pick<MistralRequestParams, "outputFormat" | "permissionMode" | "effort" | "reasoningEffort" | "allowedTools" | "disallowedTools" | "approvalStrategy" | "trust" | "maxTurns" | "maxPrice" | "maxTokens" | "workingDir" | "addDir"> & {
455
+ export declare function buildMistralRetryPrep(params: Pick<MistralRequestParams, "outputFormat" | "permissionMode" | "allowedTools" | "disallowedTools" | "approvalStrategy" | "trust" | "maxTurns" | "maxPrice" | "maxTokens" | "workingDir" | "addDir"> & {
436
456
  effectivePrompt: string;
437
457
  }, recoveryModel: string): {
438
458
  args: string[];
@@ -468,6 +488,8 @@ export interface GeminiRequestParams {
468
488
  attachments?: string[];
469
489
  /** Phase 4 slice γ: emit `--skip-trust` for fresh-workspace headless runs. */
470
490
  skipTrust?: boolean;
491
+ /** Emit `--yolo` (auto-approve all). Equivalent to approvalMode "yolo"; gated identically. */
492
+ yolo?: boolean;
471
493
  /** Slice λ: run this request inside a gateway-owned git worktree. */
472
494
  worktree?: boolean | {
473
495
  name?: string;
@@ -525,6 +547,10 @@ export interface GrokRequestParams {
525
547
  allow?: string[];
526
548
  /** Phase 4 slice θ: Grok `--deny <RULE>` (repeatable; one entry per --deny instance). */
527
549
  deny?: string[];
550
+ /** Grok 0.2.x: `--compaction-mode <summary|transcript|segments>` context control. */
551
+ compactionMode?: string;
552
+ /** Grok 0.2.x: `--compaction-detail <none|minimal|balanced|verbose>`; only affects segments mode. */
553
+ compactionDetail?: string;
528
554
  /** Slice λ: run this request inside a gateway-owned git worktree. */
529
555
  worktree?: boolean | {
530
556
  name?: string;
@@ -542,8 +568,6 @@ export interface MistralRequestParams {
542
568
  resumeLatest: boolean;
543
569
  createNewSession: boolean;
544
570
  permissionMode?: MistralAgentMode;
545
- effort?: string;
546
- reasoningEffort?: string;
547
571
  approvalStrategy: "legacy" | "mcp_managed";
548
572
  approvalPolicy?: string;
549
573
  mcpServers?: ClaudeMcpServerName[];
package/dist/index.js CHANGED
@@ -1273,6 +1273,10 @@ export function prepareClaudeRequest(params, runtime = resolveGatewayServerRunti
1273
1273
  fallbackModel: params.fallbackModel,
1274
1274
  jsonSchema: params.jsonSchema,
1275
1275
  addDir: params.addDir,
1276
+ noSessionPersistence: params.noSessionPersistence,
1277
+ settingSources: params.settingSources,
1278
+ settings: params.settings,
1279
+ tools: params.tools,
1276
1280
  }));
1277
1281
  return {
1278
1282
  corrId,
@@ -1506,7 +1510,7 @@ export function prepareGeminiRequest(params, runtime = resolveGatewayServerRunti
1506
1510
  cli: "gemini",
1507
1511
  operation: params.operation,
1508
1512
  prompt: assembledPrompt, // Use raw assembled prompt for review-context detection, not optimized
1509
- bypassRequested: params.approvalMode === "yolo",
1513
+ bypassRequested: params.approvalMode === "yolo" || params.yolo === true,
1510
1514
  fullAuto: false,
1511
1515
  requestedMcpServers,
1512
1516
  allowedTools: params.allowedTools,
@@ -1546,6 +1550,13 @@ export function prepareGeminiRequest(params, runtime = resolveGatewayServerRunti
1546
1550
  args.push("--model", resolvedModel);
1547
1551
  if (effectiveApprovalMode)
1548
1552
  args.push("--approval-mode", effectiveApprovalMode);
1553
+ // `--yolo` is functionally identical to `--approval-mode yolo`; emit it only
1554
+ // when the caller asked for yolo AND we are not already emitting
1555
+ // `--approval-mode yolo` (under mcp_managed the gate forces that mode), so
1556
+ // there is never a redundant double auto-approve flag.
1557
+ if (params.yolo && effectiveApprovalMode !== "yolo") {
1558
+ args.push("--yolo");
1559
+ }
1549
1560
  if (params.allowedTools && params.allowedTools.length > 0) {
1550
1561
  sanitizeCliArgValues(params.allowedTools, "allowedTools");
1551
1562
  params.allowedTools.forEach(tool => args.push("--allowed-tools", tool));
@@ -1694,6 +1705,12 @@ export function prepareGrokRequest(params, runtime = resolveGatewayServerRuntime
1694
1705
  args.push("--deny", rule);
1695
1706
  }
1696
1707
  }
1708
+ if (params.compactionMode) {
1709
+ args.push("--compaction-mode", params.compactionMode);
1710
+ }
1711
+ if (params.compactionDetail) {
1712
+ args.push("--compaction-detail", params.compactionDetail);
1713
+ }
1697
1714
  return {
1698
1715
  corrId,
1699
1716
  effectivePrompt,
@@ -1773,8 +1790,6 @@ export function prepareMistralRequest(params, runtime = resolveGatewayServerRunt
1773
1790
  resolvedModel,
1774
1791
  outputFormat: params.outputFormat,
1775
1792
  permissionMode: effectivePermissionMode,
1776
- effort: params.effort,
1777
- reasoningEffort: params.reasoningEffort,
1778
1793
  allowedTools: params.allowedTools,
1779
1794
  disallowedTools: params.disallowedTools,
1780
1795
  trust: params.trust,
@@ -1830,8 +1845,6 @@ export function buildMistralRetryPrep(params, recoveryModel) {
1830
1845
  permissionMode: params.approvalStrategy === "mcp_managed"
1831
1846
  ? "auto-approve"
1832
1847
  : (params.permissionMode ?? "auto-approve"),
1833
- effort: params.effort,
1834
- reasoningEffort: params.reasoningEffort,
1835
1848
  allowedTools: params.allowedTools,
1836
1849
  disallowedTools: params.disallowedTools,
1837
1850
  trust: params.trust,
@@ -1969,6 +1982,7 @@ export async function handleGeminiRequest(deps, params) {
1969
1982
  adminPolicyFiles: params.adminPolicyFiles,
1970
1983
  attachments: params.attachments,
1971
1984
  skipTrust: params.skipTrust,
1985
+ yolo: params.yolo,
1972
1986
  }, runtime);
1973
1987
  if (!("args" in prep))
1974
1988
  return prep;
@@ -2111,6 +2125,7 @@ export async function handleGeminiRequestAsync(deps, params) {
2111
2125
  adminPolicyFiles: params.adminPolicyFiles,
2112
2126
  attachments: params.attachments,
2113
2127
  skipTrust: params.skipTrust,
2128
+ yolo: params.yolo,
2114
2129
  }, runtime);
2115
2130
  if (!("args" in prep))
2116
2131
  return prep;
@@ -2210,6 +2225,8 @@ export async function handleGrokRequest(deps, params) {
2210
2225
  systemPromptOverride: params.systemPromptOverride,
2211
2226
  allow: params.allow,
2212
2227
  deny: params.deny,
2228
+ compactionMode: params.compactionMode,
2229
+ compactionDetail: params.compactionDetail,
2213
2230
  }, runtime);
2214
2231
  if (!("args" in prep))
2215
2232
  return prep;
@@ -2350,6 +2367,8 @@ export async function handleGrokRequestAsync(deps, params) {
2350
2367
  systemPromptOverride: params.systemPromptOverride,
2351
2368
  allow: params.allow,
2352
2369
  deny: params.deny,
2370
+ compactionMode: params.compactionMode,
2371
+ compactionDetail: params.compactionDetail,
2353
2372
  }, runtime);
2354
2373
  if (!("args" in prep))
2355
2374
  return prep;
@@ -2431,8 +2450,6 @@ export async function handleMistralRequest(deps, params) {
2431
2450
  model: params.model,
2432
2451
  outputFormat: params.outputFormat,
2433
2452
  permissionMode: params.permissionMode,
2434
- effort: params.effort,
2435
- reasoningEffort: params.reasoningEffort,
2436
2453
  allowedTools: params.allowedTools,
2437
2454
  disallowedTools: params.disallowedTools,
2438
2455
  approvalStrategy: params.approvalStrategy,
@@ -2582,8 +2599,6 @@ export async function handleMistralRequestAsync(deps, params) {
2582
2599
  model: params.model,
2583
2600
  outputFormat: params.outputFormat,
2584
2601
  permissionMode: params.permissionMode,
2585
- effort: params.effort,
2586
- reasoningEffort: params.reasoningEffort,
2587
2602
  allowedTools: params.allowedTools,
2588
2603
  disallowedTools: params.disallowedTools,
2589
2604
  approvalStrategy: params.approvalStrategy,
@@ -2920,6 +2935,25 @@ export function createGatewayServer(deps = {}) {
2920
2935
  .array(z.string())
2921
2936
  .optional()
2922
2937
  .describe("Claude --add-dir: additional directories the CLI is allowed to read/write beyond the process cwd. Each entry is emitted as its own --add-dir instance."),
2938
+ // Claude session / settings / tools surface (2.x)
2939
+ noSessionPersistence: z
2940
+ .boolean()
2941
+ .optional()
2942
+ .describe("Claude --no-session-persistence: do not write this session to disk (ephemeral one-shot runs; mirrors codex --ephemeral)."),
2943
+ settingSources: z
2944
+ .string()
2945
+ .min(1)
2946
+ .optional()
2947
+ .describe("Claude --setting-sources: comma-separated setting sources to load (user|project|local) for reproducible/isolated headless runs."),
2948
+ settings: z
2949
+ .string()
2950
+ .min(1)
2951
+ .optional()
2952
+ .describe("Claude --settings: path to a settings JSON file or a JSON literal of additional settings. Powerful: settings can define hooks/permissions/model; passed verbatim."),
2953
+ tools: z
2954
+ .array(z.string())
2955
+ .optional()
2956
+ .describe('Claude --tools: restrict the available built-in tool set (distinct from allowedTools permission gating). Pass [""] to disable all tools.'),
2923
2957
  worktree: WORKTREE_SCHEMA.optional(),
2924
2958
  approvalStrategy: z
2925
2959
  .enum(["legacy", "mcp_managed"])
@@ -2951,7 +2985,7 @@ export function createGatewayServer(deps = {}) {
2951
2985
  .boolean()
2952
2986
  .default(false)
2953
2987
  .describe("Bypass dedup and force a fresh CLI run even if a recent identical request exists"),
2954
- }, async ({ prompt, promptParts, model, outputFormat, sessionId, continueSession, createNewSession, allowedTools, disallowedTools, dangerouslySkipPermissions, permissionMode, agent, agents, forkSession, systemPrompt, appendSystemPrompt, maxBudgetUsd, maxTurns, effort, excludeDynamicSystemPromptSections, fallbackModel, jsonSchema, addDir, worktree, approvalStrategy, approvalPolicy, mcpServers, strictMcpConfig, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, }) => {
2988
+ }, async ({ prompt, promptParts, model, outputFormat, sessionId, continueSession, createNewSession, allowedTools, disallowedTools, dangerouslySkipPermissions, permissionMode, agent, agents, forkSession, systemPrompt, appendSystemPrompt, maxBudgetUsd, maxTurns, effort, excludeDynamicSystemPromptSections, fallbackModel, jsonSchema, addDir, noSessionPersistence, settingSources, settings, tools, worktree, approvalStrategy, approvalPolicy, mcpServers, strictMcpConfig, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, }) => {
2955
2989
  const startTime = Date.now();
2956
2990
  if (systemPrompt !== undefined && appendSystemPrompt !== undefined) {
2957
2991
  return createErrorResponse("claude", 1, "", correlationId, new Error("systemPrompt and appendSystemPrompt are mutually exclusive; use one or the other (not both)."));
@@ -2984,6 +3018,10 @@ export function createGatewayServer(deps = {}) {
2984
3018
  fallbackModel,
2985
3019
  jsonSchema,
2986
3020
  addDir,
3021
+ noSessionPersistence,
3022
+ settingSources,
3023
+ settings,
3024
+ tools,
2987
3025
  }, runtime);
2988
3026
  if (!("args" in prep))
2989
3027
  return prep;
@@ -3600,8 +3638,12 @@ export function createGatewayServer(deps = {}) {
3600
3638
  .boolean()
3601
3639
  .default(false)
3602
3640
  .describe("Emit `--skip-trust` so Gemini trusts the workspace for this session and skips the interactive trust prompt (Phase 4 slice γ). Required for headless runs in fresh workspaces."),
3641
+ yolo: z
3642
+ .boolean()
3643
+ .optional()
3644
+ .describe("Emit `--yolo` to auto-approve all actions. Equivalent to approvalMode 'yolo'; routed through the same approval gate. Under mcp_managed the gate still decides."),
3603
3645
  worktree: WORKTREE_SCHEMA.optional(),
3604
- }, async ({ prompt, promptParts, model, sessionId, resumeLatest, createNewSession, approvalMode, approvalStrategy, approvalPolicy, mcpServers, allowedTools, includeDirs, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, outputFormat, sandbox, policyFiles, adminPolicyFiles, attachments, skipTrust, worktree, }) => {
3646
+ }, async ({ prompt, promptParts, model, sessionId, resumeLatest, createNewSession, approvalMode, approvalStrategy, approvalPolicy, mcpServers, allowedTools, includeDirs, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, outputFormat, sandbox, policyFiles, adminPolicyFiles, attachments, skipTrust, yolo, worktree, }) => {
3605
3647
  return handleGeminiRequest({ sessionManager, logger, runtime }, {
3606
3648
  prompt,
3607
3649
  promptParts,
@@ -3626,6 +3668,7 @@ export function createGatewayServer(deps = {}) {
3626
3668
  adminPolicyFiles,
3627
3669
  attachments,
3628
3670
  skipTrust,
3671
+ yolo,
3629
3672
  worktree,
3630
3673
  });
3631
3674
  });
@@ -3732,8 +3775,16 @@ export function createGatewayServer(deps = {}) {
3732
3775
  .array(z.string())
3733
3776
  .optional()
3734
3777
  .describe('Grok --deny <RULE>: permission deny rules. Each entry is emitted as its own --deny instance (per `grok --help`: "Repeat to add multiple rules").'),
3778
+ compactionMode: z
3779
+ .enum(["summary", "transcript", "segments"])
3780
+ .optional()
3781
+ .describe("Grok --compaction-mode: summary (default; no pointer) | transcript (points at the raw transcript) | segments (persists per-segment markdown to grep). Sets GROK_COMPACTION_MODE."),
3782
+ compactionDetail: z
3783
+ .enum(["none", "minimal", "balanced", "verbose"])
3784
+ .optional()
3785
+ .describe("Grok --compaction-detail: verbatim segment detail (none|minimal|balanced|verbose, default verbose). Only affects `--compaction-mode segments`. Sets GROK_COMPACTION_DETAIL."),
3735
3786
  worktree: WORKTREE_SCHEMA.optional(),
3736
- }, async ({ prompt, promptParts, model, outputFormat, sessionId, resumeLatest, createNewSession, alwaysApprove, permissionMode, effort, reasoningEffort, approvalStrategy, approvalPolicy, mcpServers, allowedTools, disallowedTools, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, maxTurns, workingDir, sandbox, rules, systemPromptOverride, allow, deny, worktree, }) => {
3787
+ }, async ({ prompt, promptParts, model, outputFormat, sessionId, resumeLatest, createNewSession, alwaysApprove, permissionMode, effort, reasoningEffort, approvalStrategy, approvalPolicy, mcpServers, allowedTools, disallowedTools, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, maxTurns, workingDir, sandbox, rules, systemPromptOverride, allow, deny, compactionMode, compactionDetail, worktree, }) => {
3737
3788
  return handleGrokRequest({ sessionManager, logger, runtime }, {
3738
3789
  prompt,
3739
3790
  promptParts,
@@ -3763,6 +3814,8 @@ export function createGatewayServer(deps = {}) {
3763
3814
  systemPromptOverride,
3764
3815
  allow,
3765
3816
  deny,
3817
+ compactionMode,
3818
+ compactionDetail,
3766
3819
  worktree,
3767
3820
  });
3768
3821
  });
@@ -3798,11 +3851,6 @@ export function createGatewayServer(deps = {}) {
3798
3851
  .enum(MISTRAL_AGENT_MODES)
3799
3852
  .optional()
3800
3853
  .describe("Vibe agent mode (default|plan|accept-edits|auto-approve|chat|explore|lean). Defaults to auto-approve for programmatic use."),
3801
- effort: z
3802
- .enum(["low", "medium", "high", "xhigh", "max"])
3803
- .optional()
3804
- .describe("Vibe effort level"),
3805
- reasoningEffort: z.string().optional().describe("Reasoning effort for reasoning models"),
3806
3854
  approvalStrategy: z
3807
3855
  .enum(["legacy", "mcp_managed"])
3808
3856
  .default("legacy")
@@ -3855,7 +3903,7 @@ export function createGatewayServer(deps = {}) {
3855
3903
  .optional()
3856
3904
  .describe("Vibe --add-dir <DIR>: additional writable workspace directories. Each entry is emitted as its own --add-dir instance (Vibe states this flag may be specified multiple times)."),
3857
3905
  worktree: WORKTREE_SCHEMA.optional(),
3858
- }, async ({ prompt, promptParts, model, outputFormat, sessionId, resumeLatest, createNewSession, permissionMode, effort, reasoningEffort, approvalStrategy, approvalPolicy, mcpServers, allowedTools, disallowedTools, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, trust, maxTurns, maxPrice, maxTokens, workingDir, addDir, worktree, }) => {
3906
+ }, async ({ prompt, promptParts, model, outputFormat, sessionId, resumeLatest, createNewSession, permissionMode, approvalStrategy, approvalPolicy, mcpServers, allowedTools, disallowedTools, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, trust, maxTurns, maxPrice, maxTokens, workingDir, addDir, worktree, }) => {
3859
3907
  return handleMistralRequest({ sessionManager, logger, runtime }, {
3860
3908
  prompt,
3861
3909
  promptParts,
@@ -3865,8 +3913,6 @@ export function createGatewayServer(deps = {}) {
3865
3913
  resumeLatest,
3866
3914
  createNewSession,
3867
3915
  permissionMode,
3868
- effort,
3869
- reasoningEffort,
3870
3916
  approvalStrategy,
3871
3917
  approvalPolicy,
3872
3918
  mcpServers,
@@ -3984,6 +4030,25 @@ export function createGatewayServer(deps = {}) {
3984
4030
  .array(z.string())
3985
4031
  .optional()
3986
4032
  .describe("Claude --add-dir: additional directories the CLI is allowed to read/write beyond the process cwd. Each entry is emitted as its own --add-dir instance."),
4033
+ // Claude session / settings / tools surface (2.x)
4034
+ noSessionPersistence: z
4035
+ .boolean()
4036
+ .optional()
4037
+ .describe("Claude --no-session-persistence: do not write this session to disk (ephemeral one-shot runs; mirrors codex --ephemeral)."),
4038
+ settingSources: z
4039
+ .string()
4040
+ .min(1)
4041
+ .optional()
4042
+ .describe("Claude --setting-sources: comma-separated setting sources to load (user|project|local) for reproducible/isolated headless runs."),
4043
+ settings: z
4044
+ .string()
4045
+ .min(1)
4046
+ .optional()
4047
+ .describe("Claude --settings: path to a settings JSON file or a JSON literal of additional settings. Powerful: settings can define hooks/permissions/model; passed verbatim."),
4048
+ tools: z
4049
+ .array(z.string())
4050
+ .optional()
4051
+ .describe('Claude --tools: restrict the available built-in tool set (distinct from allowedTools permission gating). Pass [""] to disable all tools.'),
3987
4052
  worktree: WORKTREE_SCHEMA.optional(),
3988
4053
  approvalStrategy: z
3989
4054
  .enum(["legacy", "mcp_managed"])
@@ -4014,7 +4079,7 @@ export function createGatewayServer(deps = {}) {
4014
4079
  .boolean()
4015
4080
  .default(false)
4016
4081
  .describe("Bypass dedup and force a fresh CLI run even if a recent identical request exists"),
4017
- }, async ({ prompt, promptParts, model, outputFormat, sessionId, continueSession, createNewSession, allowedTools, disallowedTools, dangerouslySkipPermissions, permissionMode, agent, agents, forkSession, systemPrompt, appendSystemPrompt, maxBudgetUsd, maxTurns, effort, excludeDynamicSystemPromptSections, fallbackModel, jsonSchema, addDir, worktree, approvalStrategy, approvalPolicy, mcpServers, strictMcpConfig, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, }) => {
4082
+ }, async ({ prompt, promptParts, model, outputFormat, sessionId, continueSession, createNewSession, allowedTools, disallowedTools, dangerouslySkipPermissions, permissionMode, agent, agents, forkSession, systemPrompt, appendSystemPrompt, maxBudgetUsd, maxTurns, effort, excludeDynamicSystemPromptSections, fallbackModel, jsonSchema, addDir, noSessionPersistence, settingSources, settings, tools, worktree, approvalStrategy, approvalPolicy, mcpServers, strictMcpConfig, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, }) => {
4018
4083
  if (systemPrompt !== undefined && appendSystemPrompt !== undefined) {
4019
4084
  return createErrorResponse("claude", 1, "", correlationId, new Error("systemPrompt and appendSystemPrompt are mutually exclusive; use one or the other (not both)."));
4020
4085
  }
@@ -4046,6 +4111,10 @@ export function createGatewayServer(deps = {}) {
4046
4111
  fallbackModel,
4047
4112
  jsonSchema,
4048
4113
  addDir,
4114
+ noSessionPersistence,
4115
+ settingSources,
4116
+ settings,
4117
+ tools,
4049
4118
  }, runtime);
4050
4119
  if (!("args" in prep))
4051
4120
  return prep;
@@ -4335,8 +4404,12 @@ export function createGatewayServer(deps = {}) {
4335
4404
  .boolean()
4336
4405
  .default(false)
4337
4406
  .describe("Emit `--skip-trust` so Gemini trusts the workspace for this session and skips the interactive trust prompt (Phase 4 slice γ). Required for headless runs in fresh workspaces."),
4407
+ yolo: z
4408
+ .boolean()
4409
+ .optional()
4410
+ .describe("Emit `--yolo` to auto-approve all actions. Equivalent to approvalMode 'yolo'; routed through the same approval gate. Under mcp_managed the gate still decides."),
4338
4411
  worktree: WORKTREE_SCHEMA.optional(),
4339
- }, async ({ prompt, promptParts, model, sessionId, resumeLatest, createNewSession, approvalMode, approvalStrategy, approvalPolicy, mcpServers, allowedTools, includeDirs, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, outputFormat, sandbox, policyFiles, adminPolicyFiles, attachments, skipTrust, worktree, }) => {
4412
+ }, async ({ prompt, promptParts, model, sessionId, resumeLatest, createNewSession, approvalMode, approvalStrategy, approvalPolicy, mcpServers, allowedTools, includeDirs, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, outputFormat, sandbox, policyFiles, adminPolicyFiles, attachments, skipTrust, yolo, worktree, }) => {
4340
4413
  return handleGeminiRequestAsync({ sessionManager, asyncJobManager, logger, runtime }, {
4341
4414
  prompt,
4342
4415
  promptParts,
@@ -4360,6 +4433,7 @@ export function createGatewayServer(deps = {}) {
4360
4433
  adminPolicyFiles,
4361
4434
  attachments,
4362
4435
  skipTrust,
4436
+ yolo,
4363
4437
  worktree,
4364
4438
  });
4365
4439
  });
@@ -4462,8 +4536,16 @@ export function createGatewayServer(deps = {}) {
4462
4536
  .array(z.string())
4463
4537
  .optional()
4464
4538
  .describe("Grok --deny <RULE>: permission deny rules. Each entry → its own --deny instance."),
4539
+ compactionMode: z
4540
+ .enum(["summary", "transcript", "segments"])
4541
+ .optional()
4542
+ .describe("Grok --compaction-mode: summary (default) | transcript | segments. Sets GROK_COMPACTION_MODE."),
4543
+ compactionDetail: z
4544
+ .enum(["none", "minimal", "balanced", "verbose"])
4545
+ .optional()
4546
+ .describe("Grok --compaction-detail: segment verbatim detail (none|minimal|balanced|verbose, default verbose). Only affects segments mode. Sets GROK_COMPACTION_DETAIL."),
4465
4547
  worktree: WORKTREE_SCHEMA.optional(),
4466
- }, async ({ prompt, promptParts, model, outputFormat, sessionId, resumeLatest, createNewSession, alwaysApprove, permissionMode, effort, reasoningEffort, approvalStrategy, approvalPolicy, mcpServers, allowedTools, disallowedTools, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, maxTurns, workingDir, sandbox, rules, systemPromptOverride, allow, deny, worktree, }) => {
4548
+ }, async ({ prompt, promptParts, model, outputFormat, sessionId, resumeLatest, createNewSession, alwaysApprove, permissionMode, effort, reasoningEffort, approvalStrategy, approvalPolicy, mcpServers, allowedTools, disallowedTools, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, maxTurns, workingDir, sandbox, rules, systemPromptOverride, allow, deny, compactionMode, compactionDetail, worktree, }) => {
4467
4549
  return handleGrokRequestAsync({ sessionManager, asyncJobManager, logger, runtime }, {
4468
4550
  prompt,
4469
4551
  promptParts,
@@ -4492,6 +4574,8 @@ export function createGatewayServer(deps = {}) {
4492
4574
  systemPromptOverride,
4493
4575
  allow,
4494
4576
  deny,
4577
+ compactionMode,
4578
+ compactionDetail,
4495
4579
  worktree,
4496
4580
  });
4497
4581
  });
@@ -4524,11 +4608,6 @@ export function createGatewayServer(deps = {}) {
4524
4608
  .enum(MISTRAL_AGENT_MODES)
4525
4609
  .optional()
4526
4610
  .describe("Vibe agent mode (default|plan|accept-edits|auto-approve|chat|explore|lean). Defaults to auto-approve for programmatic use."),
4527
- effort: z
4528
- .enum(["low", "medium", "high", "xhigh", "max"])
4529
- .optional()
4530
- .describe("Vibe effort level"),
4531
- reasoningEffort: z.string().optional().describe("Reasoning effort for reasoning models"),
4532
4611
  approvalStrategy: z
4533
4612
  .enum(["legacy", "mcp_managed"])
4534
4613
  .default("legacy")
@@ -4580,7 +4659,7 @@ export function createGatewayServer(deps = {}) {
4580
4659
  .optional()
4581
4660
  .describe("Vibe --add-dir <DIR>: additional writable workspace directories. Each entry is emitted as its own --add-dir instance."),
4582
4661
  worktree: WORKTREE_SCHEMA.optional(),
4583
- }, async ({ prompt, promptParts, model, outputFormat, sessionId, resumeLatest, createNewSession, permissionMode, effort, reasoningEffort, approvalStrategy, approvalPolicy, mcpServers, allowedTools, disallowedTools, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, trust, maxTurns, maxPrice, maxTokens, workingDir, addDir, worktree, }) => {
4662
+ }, async ({ prompt, promptParts, model, outputFormat, sessionId, resumeLatest, createNewSession, permissionMode, approvalStrategy, approvalPolicy, mcpServers, allowedTools, disallowedTools, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, trust, maxTurns, maxPrice, maxTokens, workingDir, addDir, worktree, }) => {
4584
4663
  return handleMistralRequestAsync({ sessionManager, asyncJobManager, logger, runtime }, {
4585
4664
  prompt,
4586
4665
  promptParts,
@@ -4590,8 +4669,6 @@ export function createGatewayServer(deps = {}) {
4590
4669
  resumeLatest,
4591
4670
  createNewSession,
4592
4671
  permissionMode,
4593
- effort,
4594
- reasoningEffort,
4595
4672
  approvalStrategy,
4596
4673
  approvalPolicy,
4597
4674
  mcpServers,
@@ -35,32 +35,32 @@ export declare const PromptPartsSchema: z.ZodObject<{
35
35
  tools: z.ZodOptional<z.ZodBoolean>;
36
36
  context: z.ZodOptional<z.ZodBoolean>;
37
37
  }, "strict", z.ZodTypeAny, {
38
- system?: boolean | undefined;
39
38
  tools?: boolean | undefined;
39
+ system?: boolean | undefined;
40
40
  context?: boolean | undefined;
41
41
  }, {
42
- system?: boolean | undefined;
43
42
  tools?: boolean | undefined;
43
+ system?: boolean | undefined;
44
44
  context?: boolean | undefined;
45
45
  }>>;
46
46
  }, "strip", z.ZodTypeAny, {
47
47
  task: string;
48
- system?: string | undefined;
49
48
  tools?: string | undefined;
49
+ system?: string | undefined;
50
50
  context?: string | undefined;
51
51
  cacheControl?: {
52
- system?: boolean | undefined;
53
52
  tools?: boolean | undefined;
53
+ system?: boolean | undefined;
54
54
  context?: boolean | undefined;
55
55
  } | undefined;
56
56
  }, {
57
57
  task: string;
58
- system?: string | undefined;
59
58
  tools?: string | undefined;
59
+ system?: string | undefined;
60
60
  context?: string | undefined;
61
61
  cacheControl?: {
62
- system?: boolean | undefined;
63
62
  tools?: boolean | undefined;
63
+ system?: boolean | undefined;
64
64
  context?: boolean | undefined;
65
65
  } | undefined;
66
66
  }>;
@@ -98,8 +98,6 @@ export interface PrepareMistralRequestInput {
98
98
  resolvedModel?: string;
99
99
  outputFormat?: string;
100
100
  permissionMode?: MistralAgentMode;
101
- effort?: string;
102
- reasoningEffort?: string;
103
101
  allowedTools?: string[];
104
102
  /**
105
103
  * Vibe has no flag to deny tools; this is accepted in the schema for caller
@@ -391,6 +389,30 @@ export interface ClaudeHighImpactFlagsInput {
391
389
  * changing the call site).
392
390
  */
393
391
  addDir?: string[];
392
+ /**
393
+ * Claude `--no-session-persistence`: do not write this session to disk
394
+ * (one-shot / ephemeral runs; mirrors Codex `--ephemeral`).
395
+ */
396
+ noSessionPersistence?: boolean;
397
+ /**
398
+ * Claude `--setting-sources <user,project,local>`: comma-separated list of
399
+ * setting sources to load, for reproducible / isolated headless runs.
400
+ * Passed through verbatim.
401
+ */
402
+ settingSources?: string;
403
+ /**
404
+ * Claude `--settings <file-or-json>`: load additional settings from a JSON
405
+ * file path or a JSON literal. Powerful: settings can define hooks,
406
+ * permissions, and model; the value is passed through verbatim.
407
+ */
408
+ settings?: string;
409
+ /**
410
+ * Claude `--tools <tools...>`: restrict the available built-in tool set
411
+ * (distinct from `--allowed-tools` permission gating). Emitted as a single
412
+ * variadic flag mirroring `--allowed-tools`; pass `[""]` to disable all
413
+ * tools per `claude --help`. An empty array emits nothing.
414
+ */
415
+ tools?: string[];
394
416
  }
395
417
  /**
396
418
  * Emit Claude high-impact feature flags (U25) as a flat argv segment.
@@ -166,12 +166,8 @@ export function prepareMistralRequest(input) {
166
166
  }
167
167
  const mode = input.permissionMode ?? MISTRAL_DEFAULT_AGENT_MODE;
168
168
  args.push("--agent", mode);
169
- if (input.effort) {
170
- args.push("--effort", input.effort);
171
- }
172
- if (input.reasoningEffort) {
173
- args.push("--reasoning-effort", input.reasoningEffort);
174
- }
169
+ // No reasoning-effort surface on vibe: --effort / --reasoning-effort are not
170
+ // emitted (the CLI rejects them; see upstream-contracts.ts mistral block).
175
171
  if (input.allowedTools && input.allowedTools.length > 0) {
176
172
  sanitizeCliArgValues(input.allowedTools, "allowedTools");
177
173
  for (const tool of input.allowedTools) {
@@ -471,6 +467,20 @@ export function prepareClaudeHighImpactFlags(input) {
471
467
  args.push("--add-dir", dir);
472
468
  }
473
469
  }
470
+ if (input.noSessionPersistence) {
471
+ args.push("--no-session-persistence");
472
+ }
473
+ if (input.settingSources !== undefined) {
474
+ args.push("--setting-sources", input.settingSources);
475
+ }
476
+ if (input.settings !== undefined) {
477
+ args.push("--settings", input.settings);
478
+ }
479
+ if (input.tools && input.tools.length > 0) {
480
+ // Single variadic flag (mirrors --allowed-tools emission). `[""]` → `--tools ""`
481
+ // which disables all built-in tools per `claude --help`.
482
+ args.push("--tools", ...input.tools);
483
+ }
474
484
  return args;
475
485
  }
476
486
  //──────────────────────────────────────────────────────────────────────────────
@@ -49,6 +49,11 @@ export const UPSTREAM_CLI_CONTRACTS = {
49
49
  "jsonSchema",
50
50
  // Phase 4 slice ζ
51
51
  "addDir",
52
+ // Claude 2.x session / settings / tools surface
53
+ "noSessionPersistence",
54
+ "settingSources",
55
+ "settings",
56
+ "tools",
52
57
  "approvalStrategy",
53
58
  "mcpServers",
54
59
  "strictMcpConfig",
@@ -96,6 +101,12 @@ export const UPSTREAM_CLI_CONTRACTS = {
96
101
  pattern: /^[0-9]+(?:\.[0-9]+)?$/,
97
102
  description: "Budget cap in USD",
98
103
  },
104
+ // NOTE: `--probe-installed` reports --max-turns as "missing from binary"
105
+ // because claude 2.x hides it from the `--help` body. It is nonetheless a
106
+ // real, accepted flag (verified: `claude --max-turns N --help` parses
107
+ // without an "unknown option" error, while a genuinely unknown flag errors
108
+ // loudly). Keep it in the contract; the probe drift here is a known
109
+ // help-text false-positive, not a removed flag.
99
110
  "--max-turns": { arity: "one", pattern: /^[1-9][0-9]*$/, description: "Turn cap" },
100
111
  "--effort": { arity: "one", values: EFFORT_LEVELS, description: "Reasoning effort" },
101
112
  "--exclude-dynamic-system-prompt-sections": {
@@ -116,6 +127,23 @@ export const UPSTREAM_CLI_CONTRACTS = {
116
127
  },
117
128
  "--continue": { arity: "none", description: "Continue active session" },
118
129
  "--session-id": { arity: "one", description: "Session id" },
130
+ // Claude 2.x session / settings / tools surface
131
+ "--no-session-persistence": {
132
+ arity: "none",
133
+ description: "Do not persist the session to disk (ephemeral; mirrors Codex --ephemeral)",
134
+ },
135
+ "--setting-sources": {
136
+ arity: "one",
137
+ description: "Comma-separated setting sources to load (user|project|local)",
138
+ },
139
+ "--settings": {
140
+ arity: "one",
141
+ description: "Settings JSON file path or literal (can define hooks/permissions/model)",
142
+ },
143
+ "--tools": {
144
+ arity: "variadic",
145
+ description: 'Restrict the available built-in tool set ("" disables all)',
146
+ },
119
147
  },
120
148
  env: {},
121
149
  conformanceFixtures: [
@@ -162,6 +190,23 @@ export const UPSTREAM_CLI_CONTRACTS = {
162
190
  args: ["-p", "hello", "--add-dir", "/tmp/a", "--add-dir", "/tmp/b"],
163
191
  expect: "pass",
164
192
  },
193
+ {
194
+ id: "claude-session-settings-tools",
195
+ description: "Claude 2.x: --no-session-persistence, --setting-sources, --settings, and --tools (variadic) are accepted",
196
+ args: [
197
+ "-p",
198
+ "hello",
199
+ "--no-session-persistence",
200
+ "--setting-sources",
201
+ "project,local",
202
+ "--settings",
203
+ "{}",
204
+ "--tools",
205
+ "Read",
206
+ "Edit",
207
+ ],
208
+ expect: "pass",
209
+ },
165
210
  {
166
211
  // Claude CLI 2.x: stream-json requires --verbose alongside --print.
167
212
  // The gateway emits all three together; this fixture pins the combo
@@ -478,6 +523,8 @@ export const UPSTREAM_CLI_CONTRACTS = {
478
523
  "attachments",
479
524
  // Phase 4 slice γ
480
525
  "skipTrust",
526
+ // Auto-approve-all ergonomic alias (equivalent to approvalMode "yolo")
527
+ "yolo",
481
528
  ],
482
529
  flags: {
483
530
  "-p": { arity: "one", description: "Prompt text" },
@@ -503,6 +550,10 @@ export const UPSTREAM_CLI_CONTRACTS = {
503
550
  arity: "none",
504
551
  description: "Trust workspace for this session (Phase 4 slice γ)",
505
552
  },
553
+ "--yolo": {
554
+ arity: "none",
555
+ description: "Auto-approve all actions (gemini -y/--yolo). Functionally equivalent to --approval-mode yolo; the gateway emits at most one of the two.",
556
+ },
506
557
  },
507
558
  env: {},
508
559
  conformanceFixtures: [
@@ -524,6 +575,12 @@ export const UPSTREAM_CLI_CONTRACTS = {
524
575
  args: ["-p", "hello", "--skip-trust"],
525
576
  expect: "pass",
526
577
  },
578
+ {
579
+ id: "gemini-yolo",
580
+ description: "--yolo (auto-approve all) is accepted",
581
+ args: ["-p", "hello", "--yolo"],
582
+ expect: "pass",
583
+ },
527
584
  {
528
585
  id: "gemini-stream-json",
529
586
  description: "Phase 4 slice ε: -o stream-json is accepted",
@@ -576,6 +633,9 @@ export const UPSTREAM_CLI_CONTRACTS = {
576
633
  "systemPromptOverride",
577
634
  "allow",
578
635
  "deny",
636
+ // Grok 0.2.x context/compaction controls
637
+ "compactionMode",
638
+ "compactionDetail",
579
639
  ],
580
640
  flags: {
581
641
  "-p": { arity: "one", description: "Prompt text" },
@@ -665,6 +725,17 @@ export const UPSTREAM_CLI_CONTRACTS = {
665
725
  arity: "optional",
666
726
  description: "Start the session in a new git worktree, optionally named",
667
727
  },
728
+ // Grok 0.2.x context/compaction controls (both enum, env-backed):
729
+ "--compaction-mode": {
730
+ arity: "one",
731
+ values: ["summary", "transcript", "segments"],
732
+ description: "Compaction mode (default summary; sets GROK_COMPACTION_MODE). `segments` persists per-segment markdown.",
733
+ },
734
+ "--compaction-detail": {
735
+ arity: "one",
736
+ values: ["none", "minimal", "balanced", "verbose"],
737
+ description: "Segment verbatim detail (default verbose; sets GROK_COMPACTION_DETAIL). Only affects `--compaction-mode segments`.",
738
+ },
668
739
  },
669
740
  env: {},
670
741
  conformanceFixtures: [
@@ -762,6 +833,18 @@ export const UPSTREAM_CLI_CONTRACTS = {
762
833
  ],
763
834
  expect: "pass",
764
835
  },
836
+ {
837
+ id: "grok-compaction",
838
+ description: "Grok 0.2.x: --compaction-mode and --compaction-detail accepted with valid enum values",
839
+ args: ["-p", "hello", "--compaction-mode", "segments", "--compaction-detail", "balanced"],
840
+ expect: "pass",
841
+ },
842
+ {
843
+ id: "grok-compaction-mode-invalid",
844
+ description: "Grok --compaction-mode rejects a value outside the contract enum",
845
+ args: ["-p", "hello", "--compaction-mode", "aggressive"],
846
+ expect: "fail",
847
+ },
765
848
  ],
766
849
  },
767
850
  mistral: {
@@ -787,8 +870,6 @@ export const UPSTREAM_CLI_CONTRACTS = {
787
870
  "resumeLatest",
788
871
  "createNewSession",
789
872
  "permissionMode",
790
- "effort",
791
- "reasoningEffort",
792
873
  "approvalStrategy",
793
874
  "mcpServers",
794
875
  "allowedTools",
@@ -815,8 +896,12 @@ export const UPSTREAM_CLI_CONTRACTS = {
815
896
  values: ["default", "plan", "accept-edits", "auto-approve", "chat", "explore", "lean"],
816
897
  description: "Agent/permission mode",
817
898
  },
818
- "--effort": { arity: "one", description: "Reasoning effort" },
819
- "--reasoning-effort": { arity: "one", description: "Reasoning effort override" },
899
+ // NOTE: vibe has no reasoning-effort surface. `--effort` / `--reasoning-effort`
900
+ // were declared speculatively (mirroring Grok) in the provider-modernisation
901
+ // commit but were never accepted by the CLI: vibe 2.x argparse hard-rejects them
902
+ // ("error: unrecognized arguments: --effort"), failing the whole request before
903
+ // any model call. Removed from the contract, builder, and request schema; the
904
+ // mistral-effort-rejected / mistral-reasoning-effort-rejected fixtures lock it in.
820
905
  "--enabled-tools": { arity: "one", description: "Enabled tool" },
821
906
  "--resume": { arity: "one", description: "Resume session" },
822
907
  "--continue": { arity: "none", description: "Continue latest session" },
@@ -932,6 +1017,20 @@ export const UPSTREAM_CLI_CONTRACTS = {
932
1017
  env: { VIBE_ACTIVE_MODEL: "mistral-medium-3.5" },
933
1018
  expect: "pass",
934
1019
  },
1020
+ {
1021
+ id: "mistral-effort-rejected",
1022
+ description: "vibe 2.x advertises no reasoning-effort surface: a raw --effort arg is rejected by the contract (mirrors the CLI's own 'unrecognized arguments' failure)",
1023
+ args: ["-p", "hello", "--agent", "auto-approve", "--effort", "high"],
1024
+ env: { VIBE_ACTIVE_MODEL: "mistral-medium-3.5" },
1025
+ expect: "fail",
1026
+ },
1027
+ {
1028
+ id: "mistral-reasoning-effort-rejected",
1029
+ description: "vibe 2.x: a raw --reasoning-effort arg is rejected by the contract",
1030
+ args: ["-p", "hello", "--agent", "auto-approve", "--reasoning-effort", "medium"],
1031
+ env: { VIBE_ACTIVE_MODEL: "mistral-medium-3.5" },
1032
+ expect: "fail",
1033
+ },
935
1034
  ],
936
1035
  },
937
1036
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llm-cli-gateway",
3
- "version": "1.17.3",
3
+ "version": "1.17.4",
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",