llm-cli-gateway 1.17.4 → 1.17.6

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 (64) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +1 -1
  3. package/dist/approval-manager.js +0 -8
  4. package/dist/async-job-manager.d.ts +0 -113
  5. package/dist/async-job-manager.js +6 -124
  6. package/dist/cache-stats.d.ts +0 -89
  7. package/dist/cache-stats.js +0 -62
  8. package/dist/claude-mcp-config.js +0 -1
  9. package/dist/cli-updater.d.ts +0 -8
  10. package/dist/cli-updater.js +0 -12
  11. package/dist/codex-json-parser.d.ts +0 -20
  12. package/dist/codex-json-parser.js +0 -21
  13. package/dist/config.d.ts +0 -31
  14. package/dist/config.js +2 -72
  15. package/dist/db.d.ts +0 -18
  16. package/dist/db.js +0 -22
  17. package/dist/doctor.d.ts +0 -49
  18. package/dist/doctor.js +0 -47
  19. package/dist/endpoint-exposure.js +0 -1
  20. package/dist/executor.d.ts +0 -19
  21. package/dist/executor.js +3 -38
  22. package/dist/flight-recorder.d.ts +0 -26
  23. package/dist/flight-recorder.js +1 -70
  24. package/dist/gemini-json-parser.d.ts +0 -25
  25. package/dist/gemini-json-parser.js +0 -28
  26. package/dist/health.d.ts +0 -3
  27. package/dist/health.js +0 -3
  28. package/dist/index.d.ts +1 -221
  29. package/dist/index.js +14 -563
  30. package/dist/job-store.d.ts +0 -74
  31. package/dist/job-store.js +1 -73
  32. package/dist/logger.d.ts +0 -7
  33. package/dist/logger.js +0 -6
  34. package/dist/migrate-sessions.d.ts +0 -3
  35. package/dist/migrate-sessions.js +0 -16
  36. package/dist/migrate.js +1 -18
  37. package/dist/mistral-meta-json-parser.js +0 -67
  38. package/dist/model-registry.js +0 -13
  39. package/dist/pricing.d.ts +0 -46
  40. package/dist/pricing.js +0 -47
  41. package/dist/process-monitor.d.ts +0 -15
  42. package/dist/process-monitor.js +2 -31
  43. package/dist/prompt-parts.d.ts +0 -25
  44. package/dist/prompt-parts.js +0 -11
  45. package/dist/provider-status.d.ts +0 -8
  46. package/dist/provider-status.js +0 -11
  47. package/dist/request-helpers.d.ts +0 -334
  48. package/dist/request-helpers.js +1 -229
  49. package/dist/resources.d.ts +0 -20
  50. package/dist/resources.js +1 -34
  51. package/dist/retry.d.ts +0 -45
  52. package/dist/retry.js +3 -40
  53. package/dist/session-manager-pg.d.ts +0 -32
  54. package/dist/session-manager-pg.js +0 -32
  55. package/dist/session-manager.d.ts +0 -21
  56. package/dist/session-manager.js +1 -15
  57. package/dist/stream-json-parser.d.ts +0 -18
  58. package/dist/stream-json-parser.js +0 -22
  59. package/dist/upstream-contracts.d.ts +0 -55
  60. package/dist/upstream-contracts.js +0 -77
  61. package/dist/validation-orchestrator.js +0 -3
  62. package/dist/worktree-manager.d.ts +0 -9
  63. package/dist/worktree-manager.js +0 -21
  64. package/package.json +1 -1
@@ -47,9 +47,7 @@ export const UPSTREAM_CLI_CONTRACTS = {
47
47
  "excludeDynamicSystemPromptSections",
48
48
  "fallbackModel",
49
49
  "jsonSchema",
50
- // Phase 4 slice ζ
51
50
  "addDir",
52
- // Claude 2.x session / settings / tools surface
53
51
  "noSessionPersistence",
54
52
  "settingSources",
55
53
  "settings",
@@ -101,12 +99,6 @@ export const UPSTREAM_CLI_CONTRACTS = {
101
99
  pattern: /^[0-9]+(?:\.[0-9]+)?$/,
102
100
  description: "Budget cap in USD",
103
101
  },
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.
110
102
  "--max-turns": { arity: "one", pattern: /^[1-9][0-9]*$/, description: "Turn cap" },
111
103
  "--effort": { arity: "one", values: EFFORT_LEVELS, description: "Reasoning effort" },
112
104
  "--exclude-dynamic-system-prompt-sections": {
@@ -127,7 +119,6 @@ export const UPSTREAM_CLI_CONTRACTS = {
127
119
  },
128
120
  "--continue": { arity: "none", description: "Continue active session" },
129
121
  "--session-id": { arity: "one", description: "Session id" },
130
- // Claude 2.x session / settings / tools surface
131
122
  "--no-session-persistence": {
132
123
  arity: "none",
133
124
  description: "Do not persist the session to disk (ephemeral; mirrors Codex --ephemeral)",
@@ -160,16 +151,12 @@ export const UPSTREAM_CLI_CONTRACTS = {
160
151
  expect: "fail",
161
152
  },
162
153
  {
163
- // Phase 4 slice η: --fallback-model wired through prepareClaudeRequest.
164
154
  id: "claude-fallback-model",
165
155
  description: "Phase 4 slice η: --fallback-model accepted",
166
156
  args: ["-p", "hello", "--fallback-model", "claude-haiku-4-5-20251001"],
167
157
  expect: "pass",
168
158
  },
169
159
  {
170
- // Phase 4 slice η: --json-schema accepts an inline JSON Schema literal
171
- // (per `claude --help` example), not a path. Codex parity for
172
- // structured-output validation in one slice.
173
160
  id: "claude-json-schema",
174
161
  description: "Phase 4 slice η: --json-schema accepts inline JSON literal",
175
162
  args: [
@@ -183,8 +170,6 @@ export const UPSTREAM_CLI_CONTRACTS = {
183
170
  expect: "pass",
184
171
  },
185
172
  {
186
- // Phase 4 slice ζ: --add-dir wired through prepareClaudeHighImpactFlags.
187
- // Repeated once per directory; each instance has arity:"one".
188
173
  id: "claude-add-dir",
189
174
  description: "Phase 4 slice ζ: repeated --add-dir is accepted",
190
175
  args: ["-p", "hello", "--add-dir", "/tmp/a", "--add-dir", "/tmp/b"],
@@ -208,10 +193,6 @@ export const UPSTREAM_CLI_CONTRACTS = {
208
193
  expect: "pass",
209
194
  },
210
195
  {
211
- // Claude CLI 2.x: stream-json requires --verbose alongside --print.
212
- // The gateway emits all three together; this fixture pins the combo
213
- // so a future removal of --verbose breaks loudly here instead of
214
- // silently at runtime against the upstream CLI.
215
196
  id: "claude-stream-json-requires-verbose",
216
197
  description: "Claude CLI 2.x: --output-format stream-json + --include-partial-messages + --verbose accepted together",
217
198
  args: [
@@ -225,12 +206,6 @@ export const UPSTREAM_CLI_CONTRACTS = {
225
206
  expect: "pass",
226
207
  },
227
208
  {
228
- // Slice κ: when caller marks promptParts with cache_control, the
229
- // gateway emits `-p` as a standalone flag and pipes the JSON
230
- // content-blocks payload over stdin via `--input-format
231
- // stream-json`. The fixture pins the exact argv combination so
232
- // a future regression (re-emitting a positional prompt, dropping
233
- // `--input-format`, etc.) trips loudly here.
234
209
  id: "claude-input-format-stream-json",
235
210
  description: "Slice κ: `-p` standalone + --input-format stream-json + --output-format stream-json + --include-partial-messages + --verbose",
236
211
  args: [
@@ -297,15 +272,10 @@ export const UPSTREAM_CLI_CONTRACTS = {
297
272
  "images",
298
273
  "ignoreUserConfig",
299
274
  "ignoreRules",
300
- // Phase 4 slice ζ
301
275
  "workingDir",
302
276
  "addDir",
303
277
  ],
304
278
  resumeOnlyFlags: ["--last", "--all"],
305
- // Phase 4 slice α (v1.8.0) verified that `codex exec resume` accepts
306
- // `--output-schema` and `-c` (codex-cli 0.133.0 `exec resume --help`),
307
- // so they're no longer forbidden. Current resume help does not accept
308
- // session-profile or working-directory policy flags.
309
279
  resumeForbiddenFlags: ["--sandbox", "-C", "--cd", "--add-dir", "--profile"],
310
280
  flags: {
311
281
  "--last": { arity: "none", description: "Resume latest session" },
@@ -368,8 +338,6 @@ export const UPSTREAM_CLI_CONTRACTS = {
368
338
  arity: "none",
369
339
  description: "Resume picker: show all sessions without cwd filtering",
370
340
  },
371
- // The gateway emits the short form `-C`, and the advisory contract also
372
- // tracks the long `--cd` alias advertised by current Codex exec help.
373
341
  "-C": {
374
342
  arity: "one",
375
343
  description: "Working root for the session (Phase 4 slice ζ; new sessions only)",
@@ -410,9 +378,6 @@ export const UPSTREAM_CLI_CONTRACTS = {
410
378
  expect: "fail",
411
379
  },
412
380
  {
413
- // Phase 4 slice α: --output-schema IS accepted on resume per
414
- // codex-cli 0.133.0; this fixture pins the new behaviour so future
415
- // contract changes can't silently regress.
416
381
  id: "codex-resume-output-schema",
417
382
  description: "Phase 4 slice α: --output-schema accepted on resume (codex-cli 0.133.0)",
418
383
  args: ["exec", "resume", "--output-schema", "/tmp/schema.json", "session-id", "hello"],
@@ -521,9 +486,7 @@ export const UPSTREAM_CLI_CONTRACTS = {
521
486
  "policyFiles",
522
487
  "adminPolicyFiles",
523
488
  "attachments",
524
- // Phase 4 slice γ
525
489
  "skipTrust",
526
- // Auto-approve-all ergonomic alias (equivalent to approvalMode "yolo")
527
490
  "yolo",
528
491
  ],
529
492
  flags: {
@@ -623,17 +586,13 @@ export const UPSTREAM_CLI_CONTRACTS = {
623
586
  "mcpServers",
624
587
  "allowedTools",
625
588
  "disallowedTools",
626
- // Phase 4 slice δ
627
589
  "maxTurns",
628
- // Phase 4 slice ζ
629
590
  "workingDir",
630
- // Phase 4 slice θ — Grok HIGH parity
631
591
  "sandbox",
632
592
  "rules",
633
593
  "systemPromptOverride",
634
594
  "allow",
635
595
  "deny",
636
- // Grok 0.2.x context/compaction controls
637
596
  "compactionMode",
638
597
  "compactionDetail",
639
598
  ],
@@ -669,10 +628,6 @@ export const UPSTREAM_CLI_CONTRACTS = {
669
628
  arity: "one",
670
629
  description: "Working directory for the invocation (Phase 4 slice ζ)",
671
630
  },
672
- // Phase 4 slice θ — Grok HIGH parity. `--sandbox` is freeform per
673
- // `grok --help` on 0.1.210 (no `[possible values: …]` list, unlike
674
- // --effort / --permission-mode / --output-format), so we register
675
- // it without a `values` constraint.
676
631
  "--sandbox": {
677
632
  arity: "one",
678
633
  description: "Sandbox profile for filesystem + network access (Phase 4 slice θ; freeform passthrough; env: GROK_SANDBOX)",
@@ -725,7 +680,6 @@ export const UPSTREAM_CLI_CONTRACTS = {
725
680
  arity: "optional",
726
681
  description: "Start the session in a new git worktree, optionally named",
727
682
  },
728
- // Grok 0.2.x context/compaction controls (both enum, env-backed):
729
683
  "--compaction-mode": {
730
684
  arity: "one",
731
685
  values: ["summary", "transcript", "segments"],
@@ -874,13 +828,10 @@ export const UPSTREAM_CLI_CONTRACTS = {
874
828
  "mcpServers",
875
829
  "allowedTools",
876
830
  "disallowedTools",
877
- // Phase 4 slice γ
878
831
  "trust",
879
- // Phase 4 slice δ
880
832
  "maxTurns",
881
833
  "maxPrice",
882
834
  "maxTokens",
883
- // Phase 4 slice ζ
884
835
  "workingDir",
885
836
  "addDir",
886
837
  ],
@@ -896,12 +847,6 @@ export const UPSTREAM_CLI_CONTRACTS = {
896
847
  values: ["default", "plan", "accept-edits", "auto-approve", "chat", "explore", "lean"],
897
848
  description: "Agent/permission mode",
898
849
  },
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.
905
850
  "--enabled-tools": { arity: "one", description: "Enabled tool" },
906
851
  "--resume": { arity: "one", description: "Resume session" },
907
852
  "--continue": { arity: "none", description: "Continue latest session" },
@@ -916,8 +861,6 @@ export const UPSTREAM_CLI_CONTRACTS = {
916
861
  },
917
862
  "--max-price": {
918
863
  arity: "one",
919
- // Decimal-only: matches the MAX_PRICE_SCHEMA min(1e-6) lower bound
920
- // that keeps String(N) in decimal form (no scientific notation).
921
864
  pattern: /^(0|[1-9][0-9]*)(\.[0-9]+)?$/,
922
865
  description: "Cumulative cost cap in USD (Phase 4 slice δ, programmatic mode only)",
923
866
  },
@@ -1192,24 +1135,8 @@ function validateFlagValue(cli, arg, flag, value, index, violations) {
1192
1135
  });
1193
1136
  }
1194
1137
  }
1195
- /**
1196
- * Best-effort, advisory-only extraction of long-form flags from raw --help text.
1197
- * Returns a sorted array of unique `--foo-bar` style flags discovered in the output.
1198
- *
1199
- * Heuristics:
1200
- * - Matches common option declaration lines emitted by clap, yargs, commander, custom TUIs, etc.
1201
- * - Lowercases for stable comparison against our contract keys.
1202
- * - Intentionally conservative: ignores obvious noise (URLs, prose in descriptions).
1203
- *
1204
- * This powers the bidirectional drift detector (extra flags the installed binary
1205
- * advertises that our contract does not yet allow). It is NEVER used for argv
1206
- * validation — only for the upstream scanner and `upstream_contracts` probe reports.
1207
- */
1208
1138
  export function extractDiscoveredFlags(helpText) {
1209
1139
  const discovered = new Set();
1210
- // Long flags: --foo, --foo-bar, --foo_bar (some CLIs normalize _ to - in display).
1211
- // Only inspect option declaration lines so prose such as
1212
- // "(Claude Code: --allowedTools)" does not create false drift.
1213
1140
  const longRe = /--([a-z0-9][a-z0-9_-]{1,}[a-z0-9]?)/g;
1214
1141
  for (const line of helpText.split(/\r?\n/)) {
1215
1142
  const trimmed = line.trimStart();
@@ -1274,7 +1201,6 @@ export function probeInstalledCliContract(cli, timeoutMs = 5_000) {
1274
1201
  const discoveredFlags = extractDiscoveredFlags(helpText);
1275
1202
  const contractFlagSet = new Set(Object.keys(contract.flags));
1276
1203
  const extraFlags = discoveredFlags.filter(f => !contractFlagSet.has(f));
1277
- // Cheap version hint: first line that looks like a version banner
1278
1204
  const versionMatch = helpText.match(/^\s*(?:[A-Za-z][\w .-]+)?v?\d+\.\d+\S*/m);
1279
1205
  const versionHint = versionMatch ? versionMatch[0].trim().slice(0, 80) : undefined;
1280
1206
  const helpHash = createHash("sha256").update(helpText).digest("hex");
@@ -1303,9 +1229,6 @@ export function buildUpstreamContractReport(options = {}) {
1303
1229
  {
1304
1230
  executable: contract.executable,
1305
1231
  upstream: contract.upstream,
1306
- // Pure metadata pointers (changelog URLs, package name, watch
1307
- // categories). Enriched from the CliContract — the single source of
1308
- // truth — so report consumers and the scanner read the same values.
1309
1232
  upstreamMetadata: contract.upstreamMetadata
1310
1233
  ? {
1311
1234
  sourceUrls: contract.upstreamMetadata.sourceUrls,
@@ -131,9 +131,6 @@ function plannedJudgeSynthesis(input) {
131
131
  }
132
132
  function buildProviderArgs(provider, prompt) {
133
133
  if (provider === "claude" || provider === "grok" || provider === "mistral") {
134
- // Mistral Vibe mirrors Grok's `-p PROMPT` headless surface. Model selection
135
- // is via VIBE_ACTIVE_MODEL env var (no --model flag); for validation runs we
136
- // let the user's environment pick the active model.
137
134
  return ["-p", prompt];
138
135
  }
139
136
  if (provider === "codex")
@@ -25,15 +25,6 @@ export declare class WorktreeCollisionError extends WorktreeError {
25
25
  }
26
26
  export declare function sanitizeWorktreeName(input: string): string;
27
27
  export declare function createWorktree(opts: CreateWorktreeOptions): Promise<WorktreeHandle>;
28
- /**
29
- * Build a SessionCleanupHook that tears down per-session worktrees. The
30
- * hook reads `session.metadata.worktreePath` (recorded by
31
- * `resolveWorktreeForRequest`) and the optional `session.metadata.worktreeName`,
32
- * derives `repoRoot` from the path layout (`<repoRoot>/.worktrees/<name>`),
33
- * and fires `removeWorktree` asynchronously. Failures are logged by
34
- * `removeWorktree` itself — the hook always resolves so session deletion
35
- * never blocks on git.
36
- */
37
28
  export declare function createWorktreeSessionCleanupHook(logger: Logger): (session: {
38
29
  id: string;
39
30
  metadata?: Record<string, unknown>;
@@ -67,7 +67,6 @@ async function execGit(repoRoot, args, logger) {
67
67
  proc.kill("SIGKILL");
68
68
  }
69
69
  catch {
70
- // ignore — process may already be gone
71
70
  }
72
71
  rejectExec(new WorktreeError(`git ${args.join(" ")} timed out after ${GIT_TIMEOUT_MS}ms`));
73
72
  }, GIT_TIMEOUT_MS);
@@ -116,8 +115,6 @@ export async function createWorktree(opts) {
116
115
  const worktreesDir = join(opts.repoRoot, ".worktrees");
117
116
  const expectedPrefix = worktreesDir + sep;
118
117
  const worktreePath = resolvePath(opts.repoRoot, ".worktrees", name);
119
- // Defense in depth — sanitizeWorktreeName already blocks slashes, but
120
- // double-check that the resolved path is under <repoRoot>/.worktrees/.
121
118
  if (!worktreePath.startsWith(expectedPrefix)) {
122
119
  throw new WorktreeError(`resolved worktree path escapes the expected prefix: ${worktreePath} (expected under ${expectedPrefix})`);
123
120
  }
@@ -134,8 +131,6 @@ export async function createWorktree(opts) {
134
131
  if (!registered) {
135
132
  throw new WorktreeCollisionError(worktreePath);
136
133
  }
137
- // Resume reuse: the worktree already exists and is registered with git.
138
- // Return a handle pointing at it without touching anything.
139
134
  logger.info?.(`reusing existing worktree at ${worktreePath}`);
140
135
  return {
141
136
  name,
@@ -145,9 +140,6 @@ export async function createWorktree(opts) {
145
140
  };
146
141
  }
147
142
  if (registered) {
148
- // Path is registered but the directory is gone — let git prune it
149
- // before we recreate, so `worktree add` doesn't error on the stale
150
- // registration.
151
143
  const prune = await execGit(opts.repoRoot, ["worktree", "prune"], logger);
152
144
  if (prune.code !== 0) {
153
145
  logWarn(logger, `git worktree prune failed before creating ${name}: ${prune.stderr.trim()}`);
@@ -165,15 +157,6 @@ export async function createWorktree(opts) {
165
157
  createdAt: new Date().toISOString(),
166
158
  };
167
159
  }
168
- /**
169
- * Build a SessionCleanupHook that tears down per-session worktrees. The
170
- * hook reads `session.metadata.worktreePath` (recorded by
171
- * `resolveWorktreeForRequest`) and the optional `session.metadata.worktreeName`,
172
- * derives `repoRoot` from the path layout (`<repoRoot>/.worktrees/<name>`),
173
- * and fires `removeWorktree` asynchronously. Failures are logged by
174
- * `removeWorktree` itself — the hook always resolves so session deletion
175
- * never blocks on git.
176
- */
177
160
  export function createWorktreeSessionCleanupHook(logger) {
178
161
  return async (session) => {
179
162
  const meta = session.metadata ?? {};
@@ -181,8 +164,6 @@ export function createWorktreeSessionCleanupHook(logger) {
181
164
  if (!worktreePath)
182
165
  return;
183
166
  const worktreeName = typeof meta.worktreeName === "string" ? meta.worktreeName : undefined;
184
- // Layout invariant from createWorktree: <repoRoot>/.worktrees/<name>.
185
- // Strip the trailing two segments to recover repoRoot.
186
167
  const marker = `${sep}.worktrees${sep}`;
187
168
  const markerIdx = worktreePath.lastIndexOf(marker);
188
169
  if (markerIdx === -1) {
@@ -206,8 +187,6 @@ export async function removeWorktree(opts) {
206
187
  const branch = `gateway/${opts.name}`;
207
188
  const del = await execGit(opts.repoRoot, ["branch", "-D", branch], logger);
208
189
  if (del.code !== 0) {
209
- // Branch may already be gone (user deleted, never existed if add
210
- // half-failed, etc.). Demote to debug — this is best-effort cleanup.
211
190
  logger.debug?.(`git branch -D ${branch} returned code ${del.code}: ${del.stderr.trim()}`);
212
191
  }
213
192
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llm-cli-gateway",
3
- "version": "1.17.4",
3
+ "version": "1.17.6",
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",