llm-cli-gateway 1.5.4 → 1.5.13

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.
@@ -0,0 +1,620 @@
1
+ import { spawnSync } from "node:child_process";
2
+ const PERMISSION_MODES = [
3
+ "default",
4
+ "acceptEdits",
5
+ "plan",
6
+ "auto",
7
+ "dontAsk",
8
+ "bypassPermissions",
9
+ ];
10
+ const EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"];
11
+ export const UPSTREAM_CLI_CONTRACTS = {
12
+ claude: {
13
+ cli: "claude",
14
+ executable: "claude",
15
+ upstream: "Claude Code CLI",
16
+ helpArgs: [["--help"]],
17
+ maxPositionals: 0,
18
+ mcpTools: ["claude_request", "claude_request_async"],
19
+ mcpParameters: [
20
+ "prompt",
21
+ "model",
22
+ "outputFormat",
23
+ "sessionId",
24
+ "continueSession",
25
+ "createNewSession",
26
+ "allowedTools",
27
+ "disallowedTools",
28
+ "dangerouslySkipPermissions",
29
+ "permissionMode",
30
+ "agent",
31
+ "agents",
32
+ "forkSession",
33
+ "systemPrompt",
34
+ "appendSystemPrompt",
35
+ "maxBudgetUsd",
36
+ "maxTurns",
37
+ "effort",
38
+ "excludeDynamicSystemPromptSections",
39
+ "approvalStrategy",
40
+ "mcpServers",
41
+ "strictMcpConfig",
42
+ ],
43
+ flags: {
44
+ "-p": { arity: "one", description: "Prompt text" },
45
+ "--model": { arity: "one", description: "Model selector" },
46
+ "--output-format": {
47
+ arity: "one",
48
+ values: ["json", "stream-json"],
49
+ description: "Machine-readable output format",
50
+ },
51
+ "--include-partial-messages": {
52
+ arity: "none",
53
+ description: "Include partial messages in stream-json output",
54
+ },
55
+ "--allowed-tools": { arity: "variadic", description: "Allowed tool names/patterns" },
56
+ "--disallowed-tools": { arity: "variadic", description: "Disallowed tool names/patterns" },
57
+ "--permission-mode": {
58
+ arity: "one",
59
+ values: PERMISSION_MODES,
60
+ description: "Claude permission mode",
61
+ },
62
+ "--mcp-config": { arity: "one", description: "MCP config path" },
63
+ "--strict-mcp-config": { arity: "none", description: "Restrict to MCP config" },
64
+ "--agent": { arity: "one", description: "Named sub-agent" },
65
+ "--agents": { arity: "one", description: "Inline agent definitions JSON" },
66
+ "--fork-session": { arity: "none", description: "Fork current session" },
67
+ "--system-prompt": { arity: "one", description: "Replacement system prompt" },
68
+ "--append-system-prompt": { arity: "one", description: "Appended system prompt" },
69
+ "--max-budget-usd": {
70
+ arity: "one",
71
+ pattern: /^[0-9]+(?:\.[0-9]+)?$/,
72
+ description: "Budget cap in USD",
73
+ },
74
+ "--max-turns": { arity: "one", pattern: /^[1-9][0-9]*$/, description: "Turn cap" },
75
+ "--effort": { arity: "one", values: EFFORT_LEVELS, description: "Reasoning effort" },
76
+ "--exclude-dynamic-system-prompt-sections": {
77
+ arity: "none",
78
+ description: "Trim dynamic system prompt sections",
79
+ },
80
+ "--continue": { arity: "none", description: "Continue active session" },
81
+ "--session-id": { arity: "one", description: "Session id" },
82
+ },
83
+ env: {},
84
+ conformanceFixtures: [
85
+ {
86
+ id: "claude-minimal",
87
+ description: "Minimal prompt request",
88
+ args: ["-p", "hello"],
89
+ expect: "pass",
90
+ },
91
+ {
92
+ id: "claude-unsupported-flag",
93
+ description: "Unsupported flag is rejected before spawn",
94
+ args: ["-p", "hello", "--not-a-claude-flag"],
95
+ expect: "fail",
96
+ },
97
+ ],
98
+ },
99
+ codex: {
100
+ cli: "codex",
101
+ executable: "codex",
102
+ upstream: "OpenAI Codex CLI",
103
+ helpArgs: [
104
+ ["exec", "--help"],
105
+ ["exec", "resume", "--help"],
106
+ ],
107
+ command: { requiredFirstArg: "exec", optionalSecondArg: "resume" },
108
+ maxPositionals: 1,
109
+ resumeMaxPositionals: 2,
110
+ mcpTools: ["codex_request", "codex_request_async"],
111
+ mcpParameters: [
112
+ "prompt",
113
+ "model",
114
+ "fullAuto",
115
+ "sandboxMode",
116
+ "askForApproval",
117
+ "useLegacyFullAutoFlag",
118
+ "dangerouslyBypassApprovalsAndSandbox",
119
+ "approvalStrategy",
120
+ "mcpServers",
121
+ "sessionId",
122
+ "resumeLatest",
123
+ "createNewSession",
124
+ "outputFormat",
125
+ "outputSchema",
126
+ "search",
127
+ "profile",
128
+ "configOverrides",
129
+ "ephemeral",
130
+ "images",
131
+ "ignoreUserConfig",
132
+ "ignoreRules",
133
+ ],
134
+ resumeOnlyFlags: ["--last"],
135
+ resumeForbiddenFlags: [
136
+ "--sandbox",
137
+ "--ask-for-approval",
138
+ "--full-auto",
139
+ "--output-schema",
140
+ "--search",
141
+ "-c",
142
+ ],
143
+ flags: {
144
+ "--last": { arity: "none", description: "Resume latest session" },
145
+ "--model": { arity: "one", description: "Model selector" },
146
+ "--sandbox": {
147
+ arity: "one",
148
+ values: ["read-only", "workspace-write", "danger-full-access"],
149
+ description: "Sandbox policy",
150
+ },
151
+ "--ask-for-approval": {
152
+ arity: "one",
153
+ values: ["untrusted", "on-request", "never"],
154
+ description: "Approval policy",
155
+ },
156
+ "--full-auto": { arity: "none", description: "Legacy full-auto shortcut" },
157
+ "--dangerously-bypass-approvals-and-sandbox": {
158
+ arity: "none",
159
+ description: "Disable approvals and sandbox",
160
+ },
161
+ "--json": { arity: "none", description: "JSONL event stream" },
162
+ "--skip-git-repo-check": { arity: "none", description: "Allow non-git cwd" },
163
+ "--output-schema": { arity: "one", description: "Structured output JSON schema path" },
164
+ "--search": { arity: "none", description: "Enable web search" },
165
+ "--profile": { arity: "one", description: "Config profile" },
166
+ "-c": {
167
+ arity: "one",
168
+ pattern: /^[a-zA-Z0-9._]+=([^\r\n]*)$/,
169
+ description: "Config override key=value",
170
+ },
171
+ "--ephemeral": { arity: "none", description: "Do not persist session" },
172
+ "-i": { arity: "one", description: "Image path" },
173
+ "--ignore-user-config": { arity: "none", description: "Ignore user config" },
174
+ "--ignore-rules": { arity: "none", description: "Ignore rule files" },
175
+ },
176
+ env: {},
177
+ conformanceFixtures: [
178
+ {
179
+ id: "codex-minimal",
180
+ description: "Minimal exec prompt",
181
+ args: ["exec", "--skip-git-repo-check", "hello"],
182
+ expect: "pass",
183
+ },
184
+ {
185
+ id: "codex-invalid-sandbox",
186
+ description: "Unsupported sandbox enum is rejected",
187
+ args: ["exec", "--sandbox", "workspace", "hello"],
188
+ expect: "fail",
189
+ },
190
+ {
191
+ id: "codex-resume-output-schema",
192
+ description: "Resume-incompatible output schema flag is rejected",
193
+ args: ["exec", "resume", "--output-schema", "/tmp/schema.json", "session-id", "hello"],
194
+ expect: "fail",
195
+ },
196
+ ],
197
+ },
198
+ gemini: {
199
+ cli: "gemini",
200
+ executable: "gemini",
201
+ upstream: "Google Gemini CLI",
202
+ helpArgs: [["--help"]],
203
+ maxPositionals: 0,
204
+ mcpTools: ["gemini_request", "gemini_request_async"],
205
+ mcpParameters: [
206
+ "prompt",
207
+ "model",
208
+ "sessionId",
209
+ "resumeLatest",
210
+ "createNewSession",
211
+ "approvalMode",
212
+ "approvalStrategy",
213
+ "mcpServers",
214
+ "allowedTools",
215
+ "includeDirs",
216
+ "outputFormat",
217
+ "sandbox",
218
+ "policyFiles",
219
+ "adminPolicyFiles",
220
+ "attachments",
221
+ ],
222
+ flags: {
223
+ "-p": { arity: "one", description: "Prompt text" },
224
+ "--model": { arity: "one", description: "Model selector" },
225
+ "--approval-mode": {
226
+ arity: "one",
227
+ values: ["default", "auto_edit", "yolo", "plan"],
228
+ description: "Approval mode",
229
+ },
230
+ "--allowed-tools": { arity: "one", description: "Allowed tool" },
231
+ "--allowed-mcp-server-names": { arity: "one", description: "Allowed MCP server" },
232
+ "--include-directories": { arity: "one", description: "Included directory" },
233
+ "-s": { arity: "none", description: "Sandbox mode" },
234
+ "--policy": { arity: "one", description: "Policy file path" },
235
+ "--admin-policy": { arity: "one", description: "Admin policy file path" },
236
+ "-o": { arity: "one", values: ["json"], description: "Output format" },
237
+ "--session-id": { arity: "one", description: "Fresh session UUID" },
238
+ "--resume": { arity: "one", description: "Resume session" },
239
+ },
240
+ env: {},
241
+ conformanceFixtures: [
242
+ {
243
+ id: "gemini-minimal",
244
+ description: "Minimal prompt request",
245
+ args: ["-p", "hello"],
246
+ expect: "pass",
247
+ },
248
+ {
249
+ id: "gemini-unsupported-flag",
250
+ description: "Unsupported flag is rejected before spawn",
251
+ args: ["-p", "hello", "--not-a-gemini-flag"],
252
+ expect: "fail",
253
+ },
254
+ ],
255
+ },
256
+ grok: {
257
+ cli: "grok",
258
+ executable: "grok",
259
+ upstream: "xAI Grok CLI",
260
+ helpArgs: [["--help"]],
261
+ maxPositionals: 0,
262
+ mcpTools: ["grok_request", "grok_request_async"],
263
+ mcpParameters: [
264
+ "prompt",
265
+ "model",
266
+ "outputFormat",
267
+ "sessionId",
268
+ "resumeLatest",
269
+ "createNewSession",
270
+ "alwaysApprove",
271
+ "permissionMode",
272
+ "effort",
273
+ "reasoningEffort",
274
+ "approvalStrategy",
275
+ "mcpServers",
276
+ "allowedTools",
277
+ "disallowedTools",
278
+ ],
279
+ flags: {
280
+ "-p": { arity: "one", description: "Prompt text" },
281
+ "--model": { arity: "one", description: "Model selector" },
282
+ "--output-format": {
283
+ arity: "one",
284
+ values: ["plain", "json", "streaming-json"],
285
+ description: "Output format",
286
+ },
287
+ "--always-approve": { arity: "none", description: "Approve tool use automatically" },
288
+ "--permission-mode": {
289
+ arity: "one",
290
+ values: PERMISSION_MODES,
291
+ description: "Permission mode",
292
+ },
293
+ "--effort": { arity: "one", values: EFFORT_LEVELS, description: "Reasoning effort" },
294
+ "--reasoning-effort": { arity: "one", description: "Reasoning effort override" },
295
+ "--tools": { arity: "one", description: "Comma-separated allowed tools" },
296
+ "--disallowed-tools": {
297
+ arity: "one",
298
+ description: "Comma-separated disallowed tools",
299
+ },
300
+ "--resume": { arity: "one", description: "Resume session" },
301
+ "--continue": { arity: "none", description: "Continue latest session" },
302
+ },
303
+ env: {},
304
+ conformanceFixtures: [
305
+ {
306
+ id: "grok-minimal",
307
+ description: "Minimal prompt request",
308
+ args: ["-p", "hello"],
309
+ expect: "pass",
310
+ },
311
+ {
312
+ id: "grok-unsupported-flag",
313
+ description: "Unsupported flag is rejected before spawn",
314
+ args: ["-p", "hello", "--not-a-grok-flag"],
315
+ expect: "fail",
316
+ },
317
+ ],
318
+ },
319
+ mistral: {
320
+ cli: "mistral",
321
+ executable: "vibe",
322
+ upstream: "Mistral Vibe CLI",
323
+ helpArgs: [["--help"]],
324
+ maxPositionals: 0,
325
+ mcpTools: ["mistral_request", "mistral_request_async"],
326
+ mcpParameters: [
327
+ "prompt",
328
+ "model",
329
+ "outputFormat",
330
+ "sessionId",
331
+ "resumeLatest",
332
+ "createNewSession",
333
+ "permissionMode",
334
+ "effort",
335
+ "reasoningEffort",
336
+ "approvalStrategy",
337
+ "mcpServers",
338
+ "allowedTools",
339
+ "disallowedTools",
340
+ ],
341
+ flags: {
342
+ "-p": { arity: "one", description: "Prompt text" },
343
+ "--output-format": {
344
+ arity: "one",
345
+ values: ["plain", "json", "stream-json"],
346
+ description: "Output format",
347
+ },
348
+ "--agent": {
349
+ arity: "one",
350
+ values: ["default", "plan", "accept-edits", "auto-approve", "chat", "explore", "lean"],
351
+ description: "Agent/permission mode",
352
+ },
353
+ "--effort": { arity: "one", description: "Reasoning effort" },
354
+ "--reasoning-effort": { arity: "one", description: "Reasoning effort override" },
355
+ "--enabled-tools": { arity: "one", description: "Enabled tool" },
356
+ "--resume": { arity: "one", description: "Resume session" },
357
+ "--continue": { arity: "none", description: "Continue latest session" },
358
+ },
359
+ env: {
360
+ VIBE_ACTIVE_MODEL: {
361
+ arity: "one",
362
+ pattern: /^[^\s\u0000-\u001f\u007f]+$/,
363
+ description: "Active model selector; Vibe uses env instead of a --model flag",
364
+ },
365
+ },
366
+ conformanceFixtures: [
367
+ {
368
+ id: "mistral-minimal",
369
+ description: "Minimal prompt request with env-selected model",
370
+ args: ["-p", "hello", "--agent", "auto-approve"],
371
+ env: { VIBE_ACTIVE_MODEL: "devstral-medium" },
372
+ expect: "pass",
373
+ },
374
+ {
375
+ id: "mistral-unsupported-env",
376
+ description: "Unsupported env var is rejected before spawn",
377
+ args: ["-p", "hello"],
378
+ env: { CODEX_MODEL: "gpt-5.5" },
379
+ expect: "fail",
380
+ },
381
+ ],
382
+ },
383
+ };
384
+ export function validateUpstreamCliArgs(cli, args) {
385
+ const contract = UPSTREAM_CLI_CONTRACTS[cli];
386
+ const violations = [];
387
+ let i = 0;
388
+ let resumeContext = false;
389
+ const positionals = [];
390
+ if (contract.command) {
391
+ if (args[0] !== contract.command.requiredFirstArg) {
392
+ violations.push({
393
+ cli,
394
+ arg: args[0],
395
+ index: 0,
396
+ message: `${cli} argv must start with "${contract.command.requiredFirstArg}"`,
397
+ });
398
+ return { ok: false, violations };
399
+ }
400
+ i = 1;
401
+ if (args[i] === contract.command.optionalSecondArg) {
402
+ resumeContext = true;
403
+ i += 1;
404
+ }
405
+ }
406
+ for (; i < args.length; i++) {
407
+ const arg = args[i];
408
+ const flag = contract.flags[arg];
409
+ if (!flag) {
410
+ if (arg.startsWith("-")) {
411
+ violations.push({
412
+ cli,
413
+ arg,
414
+ index: i,
415
+ message: `Unsupported ${cli} CLI flag "${arg}" for bundled upstream contract`,
416
+ });
417
+ }
418
+ else {
419
+ positionals.push(arg);
420
+ }
421
+ continue;
422
+ }
423
+ if (resumeContext && contract.resumeForbiddenFlags?.includes(arg)) {
424
+ violations.push({
425
+ cli,
426
+ arg,
427
+ index: i,
428
+ message: `${cli} flag "${arg}" is not accepted by the resume command contract`,
429
+ });
430
+ }
431
+ if (!resumeContext && contract.resumeOnlyFlags?.includes(arg)) {
432
+ violations.push({
433
+ cli,
434
+ arg,
435
+ index: i,
436
+ message: `${cli} flag "${arg}" is only valid with the resume command contract`,
437
+ });
438
+ }
439
+ if (flag.arity === "none") {
440
+ continue;
441
+ }
442
+ if (flag.arity === "one") {
443
+ const value = args[i + 1];
444
+ if (value === undefined) {
445
+ violations.push({
446
+ cli,
447
+ arg,
448
+ index: i,
449
+ message: `${cli} flag "${arg}" requires one value`,
450
+ });
451
+ continue;
452
+ }
453
+ validateFlagValue(cli, arg, flag, value, i + 1, violations);
454
+ i += 1;
455
+ continue;
456
+ }
457
+ let consumed = 0;
458
+ while (i + 1 < args.length && !args[i + 1].startsWith("-")) {
459
+ validateFlagValue(cli, arg, flag, args[i + 1], i + 1, violations);
460
+ i += 1;
461
+ consumed += 1;
462
+ }
463
+ if (consumed === 0) {
464
+ violations.push({
465
+ cli,
466
+ arg,
467
+ index: i,
468
+ message: `${cli} flag "${arg}" requires at least one value`,
469
+ });
470
+ }
471
+ }
472
+ const maxPositionals = resumeContext && contract.resumeMaxPositionals !== undefined
473
+ ? contract.resumeMaxPositionals
474
+ : contract.maxPositionals;
475
+ if (positionals.length > maxPositionals) {
476
+ violations.push({
477
+ cli,
478
+ message: `${cli} argv has ${positionals.length} positional values; upstream contract allows ${maxPositionals}`,
479
+ });
480
+ }
481
+ return { ok: violations.length === 0, violations };
482
+ }
483
+ export function assertUpstreamCliArgs(cli, args) {
484
+ const result = validateUpstreamCliArgs(cli, args);
485
+ if (!result.ok) {
486
+ const details = result.violations.map(v => v.message).join("; ");
487
+ throw new Error(`Upstream ${cli} CLI contract violation: ${details}`);
488
+ }
489
+ }
490
+ export function validateUpstreamCliEnv(cli, env) {
491
+ if (!env || Object.keys(env).length === 0)
492
+ return { ok: true, violations: [] };
493
+ const contract = UPSTREAM_CLI_CONTRACTS[cli];
494
+ const violations = [];
495
+ for (const [key, value] of Object.entries(env)) {
496
+ const envContract = contract.env?.[key];
497
+ if (!envContract) {
498
+ violations.push({
499
+ cli,
500
+ arg: key,
501
+ message: `Unsupported ${cli} CLI environment variable "${key}" for bundled upstream contract`,
502
+ });
503
+ continue;
504
+ }
505
+ validateFlagValue(cli, key, envContract, value, undefined, violations);
506
+ }
507
+ return { ok: violations.length === 0, violations };
508
+ }
509
+ export function assertUpstreamCliEnv(cli, env) {
510
+ const result = validateUpstreamCliEnv(cli, env);
511
+ if (!result.ok) {
512
+ const details = result.violations.map(v => v.message).join("; ");
513
+ throw new Error(`Upstream ${cli} CLI environment contract violation: ${details}`);
514
+ }
515
+ }
516
+ function validateFlagValue(cli, arg, flag, value, index, violations) {
517
+ if (flag.values && !flag.values.includes(value)) {
518
+ violations.push({
519
+ cli,
520
+ arg: value,
521
+ ...(index === undefined ? {} : { index }),
522
+ message: `${cli} flag "${arg}" does not accept value "${value}"`,
523
+ });
524
+ }
525
+ if (flag.pattern && !flag.pattern.test(value)) {
526
+ violations.push({
527
+ cli,
528
+ arg: value,
529
+ ...(index === undefined ? {} : { index }),
530
+ message: `${cli} flag "${arg}" value "${value}" does not match required shape`,
531
+ });
532
+ }
533
+ }
534
+ export function probeInstalledCliContract(cli, timeoutMs = 5_000) {
535
+ const contract = UPSTREAM_CLI_CONTRACTS[cli];
536
+ const outputs = [];
537
+ const warnings = [];
538
+ for (const helpArgs of contract.helpArgs) {
539
+ const result = spawnSync(contract.executable, helpArgs, {
540
+ encoding: "utf8",
541
+ timeout: timeoutMs,
542
+ maxBuffer: 1024 * 1024,
543
+ });
544
+ if (result.error) {
545
+ return {
546
+ cli,
547
+ executable: contract.executable,
548
+ available: false,
549
+ checkedHelpCommands: contract.helpArgs,
550
+ missingFlags: [],
551
+ warnings: [result.error.message],
552
+ };
553
+ }
554
+ outputs.push(`${result.stdout ?? ""}\n${result.stderr ?? ""}`);
555
+ if (result.status !== 0) {
556
+ warnings.push(`${contract.executable} ${helpArgs.join(" ")} exited with status ${result.status}`);
557
+ }
558
+ }
559
+ const helpText = outputs.join("\n");
560
+ const missingFlags = Object.keys(contract.flags).filter(flag => !helpText.includes(flag));
561
+ return {
562
+ cli,
563
+ executable: contract.executable,
564
+ available: true,
565
+ checkedHelpCommands: contract.helpArgs,
566
+ missingFlags,
567
+ warnings,
568
+ };
569
+ }
570
+ export function buildUpstreamContractReport(options = {}) {
571
+ const selected = options.cli ? [options.cli] : Object.keys(UPSTREAM_CLI_CONTRACTS);
572
+ const contracts = Object.fromEntries(selected.map(cli => {
573
+ const contract = UPSTREAM_CLI_CONTRACTS[cli];
574
+ return [
575
+ cli,
576
+ {
577
+ executable: contract.executable,
578
+ upstream: contract.upstream,
579
+ command: contract.command ?? null,
580
+ helpArgs: contract.helpArgs,
581
+ mcpTools: contract.mcpTools,
582
+ mcpParameters: contract.mcpParameters,
583
+ flags: Object.fromEntries(Object.entries(contract.flags).map(([name, flag]) => [
584
+ name,
585
+ {
586
+ arity: flag.arity,
587
+ values: flag.values ?? null,
588
+ pattern: flag.pattern?.source ?? null,
589
+ description: flag.description,
590
+ },
591
+ ])),
592
+ env: Object.fromEntries(Object.entries(contract.env ?? {}).map(([name, envContract]) => [
593
+ name,
594
+ {
595
+ values: envContract.values ?? null,
596
+ pattern: envContract.pattern?.source ?? null,
597
+ description: envContract.description,
598
+ },
599
+ ])),
600
+ maxPositionals: contract.maxPositionals,
601
+ resumeMaxPositionals: contract.resumeMaxPositionals ?? null,
602
+ resumeOnlyFlags: contract.resumeOnlyFlags ?? [],
603
+ resumeForbiddenFlags: contract.resumeForbiddenFlags ?? [],
604
+ conformanceFixtures: contract.conformanceFixtures.map(fixture => ({
605
+ id: fixture.id,
606
+ description: fixture.description,
607
+ expect: fixture.expect,
608
+ })),
609
+ },
610
+ ];
611
+ }));
612
+ return {
613
+ schemaVersion: "upstream-cli-contracts.v1",
614
+ generatedAt: new Date().toISOString(),
615
+ contracts,
616
+ installedProbe: options.probeInstalled
617
+ ? Object.fromEntries(selected.map(cli => [cli, probeInstalledCliContract(cli)]))
618
+ : null,
619
+ };
620
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llm-cli-gateway",
3
- "version": "1.5.4",
3
+ "version": "1.5.13",
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",
@@ -63,6 +63,7 @@
63
63
  "doctor": "node dist/index.js doctor --json",
64
64
  "migrate": "node dist/migrate.js",
65
65
  "test": "vitest run",
66
+ "test:ci": "vitest run --pool=forks --maxWorkers=1",
66
67
  "test:coverage": "vitest run --coverage",
67
68
  "test:watch": "vitest",
68
69
  "test:unit": "vitest run src/__tests__/executor.test.ts",
@@ -81,8 +82,8 @@
81
82
  "release:docker": "docker compose -f docker-compose.personal.yml build"
82
83
  },
83
84
  "dependencies": {
84
- "@modelcontextprotocol/sdk": "^1.0.0",
85
- "better-sqlite3": "^12.9.0",
85
+ "@modelcontextprotocol/sdk": "^1.29.0",
86
+ "better-sqlite3": "^12.10.0",
86
87
  "ioredis": "^5.4.1",
87
88
  "pg": "^8.12.0",
88
89
  "toml": "^3.0.0",
@@ -92,13 +93,17 @@
92
93
  "@types/better-sqlite3": "^7.6.0",
93
94
  "@types/node": "^20.19.30",
94
95
  "@types/pg": "^8.11.10",
95
- "@typescript-eslint/eslint-plugin": "^6.0.0",
96
- "@typescript-eslint/parser": "^6.0.0",
96
+ "@typescript-eslint/eslint-plugin": "^8.59.4",
97
+ "@typescript-eslint/parser": "^8.59.4",
97
98
  "@vitest/coverage-v8": "^4.1.2",
98
- "eslint": "^8.0.0",
99
+ "eslint": "^8.57.1",
99
100
  "eslint-config-prettier": "^9.0.0",
100
101
  "prettier": "^3.0.0",
101
102
  "typescript": "^5.0.0",
102
103
  "vitest": "^4.0.18"
104
+ },
105
+ "overrides": {
106
+ "type-is": "2.0.1",
107
+ "content-type": "1.0.5"
103
108
  }
104
109
  }