agent-gate-installer 1.4.0 → 1.4.1

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/bin/install.mjs CHANGED
@@ -179,6 +179,11 @@ async function install() {
179
179
 
180
180
  mkdirSync(CLAUDE_HOME, { recursive: true });
181
181
 
182
+ const venvDirectory = join(INSTALL_DIR, ".venv");
183
+ const venvPython = getVenvPython(venvDirectory);
184
+
185
+ writeMcpConfigFile(venvPython);
186
+
182
187
  if (existsSync(join(INSTALL_DIR, ".git"))) {
183
188
  log(" ~ agent-gate already cloned, pulling latest...");
184
189
  try {
@@ -199,9 +204,6 @@ async function install() {
199
204
  }
200
205
  }
201
206
 
202
- const venvDirectory = join(INSTALL_DIR, ".venv");
203
- const venvPython = getVenvPython(venvDirectory);
204
-
205
207
  if (existsSync(venvDirectory)) {
206
208
  log(" ~ venv already exists");
207
209
  } else {
@@ -236,8 +238,6 @@ async function install() {
236
238
  registerMcpServer(settings, venvPython);
237
239
  writeSettings(settings);
238
240
 
239
- writeMcpConfigFile(venvPython);
240
-
241
241
  log(" + Verifying installation...");
242
242
  try {
243
243
  run(`"${venvPython}" -c "from agent_gate.server import create_mcp; print('OK')"`);
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Tests for writeMcpConfigFile behavior in install.mjs.
5
+ *
6
+ * Verifies that /tmp/agent-gate-mcp-config.json is written even when
7
+ * earlier install steps (clone, venv, pip) fail.
8
+ */
9
+
10
+ import { existsSync, readFileSync, rmSync, writeFileSync, mkdirSync } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { execSync } from "node:child_process";
13
+
14
+ const MCP_CONFIG_PATH = "/tmp/agent-gate-mcp-config.json";
15
+ let passed = 0;
16
+ let failed = 0;
17
+
18
+ function cleanup() {
19
+ try { rmSync(MCP_CONFIG_PATH); } catch { /* ok */ }
20
+ }
21
+
22
+ function assert(condition, message) {
23
+ if (condition) {
24
+ console.log(` PASS: ${message}`);
25
+ passed++;
26
+ } else {
27
+ console.log(` FAIL: ${message}`);
28
+ failed++;
29
+ }
30
+ }
31
+
32
+ // --- Test 1: writeMcpConfigFile writes correct content ---
33
+ console.log("\nTest 1: writeMcpConfigFile writes correct JSON");
34
+ cleanup();
35
+ {
36
+ // Inline the function logic to test it in isolation
37
+ const venvPython = "/root/.claude/agent-gate/.venv/bin/python";
38
+ const INSTALL_DIR = "/root/.claude/agent-gate";
39
+ const config = {
40
+ mcpServers: {
41
+ "agent-gate": {
42
+ type: "stdio",
43
+ command: venvPython,
44
+ args: [join(INSTALL_DIR, "src", "agent_gate", "server.py")],
45
+ },
46
+ },
47
+ };
48
+ writeFileSync(MCP_CONFIG_PATH, JSON.stringify(config, null, 4) + "\n", "utf8");
49
+
50
+ assert(existsSync(MCP_CONFIG_PATH), "File exists at /tmp/agent-gate-mcp-config.json");
51
+
52
+ const content = JSON.parse(readFileSync(MCP_CONFIG_PATH, "utf8"));
53
+ assert(content.mcpServers?.["agent-gate"] !== undefined, "Has agent-gate MCP server entry");
54
+ assert(content.mcpServers["agent-gate"].type === "stdio", "Type is stdio");
55
+ assert(content.mcpServers["agent-gate"].command === venvPython, "Command points to venv python");
56
+ assert(
57
+ content.mcpServers["agent-gate"].args[0].endsWith("server.py"),
58
+ "Args point to server.py"
59
+ );
60
+ }
61
+ cleanup();
62
+
63
+ // --- Test 2: Simulate install failure — MCP config should still be written ---
64
+ console.log("\nTest 2: MCP config written even when install exits early");
65
+ cleanup();
66
+ {
67
+ // Run the installer with a bad GH_TOKEN in non-interactive mode.
68
+ // The clone step will fail, but we want the MCP config to exist.
69
+ try {
70
+ execSync(
71
+ `GH_TOKEN=bad_token node "${join(import.meta.dirname, "install.mjs")}" --non-interactive`,
72
+ { encoding: "utf8", stdio: "pipe", timeout: 30000 }
73
+ );
74
+ } catch {
75
+ // Expected — install fails at clone step
76
+ }
77
+
78
+ assert(
79
+ existsSync(MCP_CONFIG_PATH),
80
+ "MCP config file exists after failed install (written before clone)"
81
+ );
82
+ }
83
+ cleanup();
84
+
85
+ // --- Test 3: Simulate install with existing clone but broken pip ---
86
+ console.log("\nTest 3: MCP config written even when pip install fails");
87
+ cleanup();
88
+ {
89
+ // Create a fake INSTALL_DIR so clone is skipped, but venv/pip will fail
90
+ const fakeInstallDir = "/tmp/agent-gate-test-install";
91
+ try { rmSync(fakeInstallDir, { recursive: true }); } catch { /* ok */ }
92
+ mkdirSync(join(fakeInstallDir, ".git"), { recursive: true });
93
+
94
+ try {
95
+ execSync(
96
+ `HOME=/tmp/agent-gate-test-home GH_TOKEN=x node "${join(import.meta.dirname, "install.mjs")}" --non-interactive`,
97
+ { encoding: "utf8", stdio: "pipe", timeout: 30000, env: { ...process.env, HOME: "/tmp/agent-gate-test-home" } }
98
+ );
99
+ } catch {
100
+ // Expected — install fails at venv/pip step
101
+ }
102
+
103
+ assert(
104
+ existsSync(MCP_CONFIG_PATH),
105
+ "MCP config file exists after pip failure (written before pip)"
106
+ );
107
+
108
+ try { rmSync(fakeInstallDir, { recursive: true }); } catch { /* ok */ }
109
+ try { rmSync("/tmp/agent-gate-test-home", { recursive: true }); } catch { /* ok */ }
110
+ }
111
+ cleanup();
112
+
113
+ // --- Summary ---
114
+ console.log(`\n${passed} passed, ${failed} failed\n`);
115
+ process.exit(failed > 0 ? 1 : 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-gate-installer",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "One-command installer for agent-gate prompt evaluation gate",
5
5
  "type": "module",
6
6
  "bin": {