lockin-mcp 1.0.4 → 1.0.7
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/README.md +1 -1
- package/dist/http-auth.d.ts +4 -3
- package/dist/http-auth.d.ts.map +1 -1
- package/dist/http-auth.js +7 -3
- package/dist/http-auth.js.map +1 -1
- package/dist/http-auth.test.js +9 -3
- package/dist/http-auth.test.js.map +1 -1
- package/dist/index.js +64 -41
- package/dist/index.js.map +1 -1
- package/dist/install.js +9 -0
- package/dist/install.js.map +1 -1
- package/dist/installer/agent-instructions.d.ts.map +1 -1
- package/dist/installer/agent-instructions.js +0 -1
- package/dist/installer/agent-instructions.js.map +1 -1
- package/dist/installer/agents.d.ts +1 -1
- package/dist/installer/agents.d.ts.map +1 -1
- package/dist/installer/agents.js +11 -89
- package/dist/installer/agents.js.map +1 -1
- package/dist/installer/background-service.d.ts +8 -1
- package/dist/installer/background-service.d.ts.map +1 -1
- package/dist/installer/background-service.js +22 -2
- package/dist/installer/background-service.js.map +1 -1
- package/dist/installer/dev-reset.d.ts +16 -0
- package/dist/installer/dev-reset.d.ts.map +1 -0
- package/dist/installer/dev-reset.js +239 -0
- package/dist/installer/dev-reset.js.map +1 -0
- package/dist/installer/dev-reset.test.d.ts +2 -0
- package/dist/installer/dev-reset.test.d.ts.map +1 -0
- package/dist/installer/dev-reset.test.js +23 -0
- package/dist/installer/dev-reset.test.js.map +1 -0
- package/dist/installer/port.d.ts +8 -0
- package/dist/installer/port.d.ts.map +1 -1
- package/dist/installer/port.js +76 -4
- package/dist/installer/port.js.map +1 -1
- package/dist/installer/port.test.d.ts +2 -0
- package/dist/installer/port.test.d.ts.map +1 -0
- package/dist/installer/port.test.js +55 -0
- package/dist/installer/port.test.js.map +1 -0
- package/dist/installer/run.js +34 -18
- package/dist/installer/run.js.map +1 -1
- package/dist/license-check.d.ts +3 -1
- package/dist/license-check.d.ts.map +1 -1
- package/dist/license-check.js +18 -9
- package/dist/license-check.js.map +1 -1
- package/dist/license-check.test.d.ts +2 -0
- package/dist/license-check.test.d.ts.map +1 -0
- package/dist/license-check.test.js +64 -0
- package/dist/license-check.test.js.map +1 -0
- package/dist/license-guard.d.ts.map +1 -1
- package/dist/license-guard.js +38 -1
- package/dist/license-guard.js.map +1 -1
- package/dist/license-guard.test.js +48 -1
- package/dist/license-guard.test.js.map +1 -1
- package/dist/relay-client.d.ts +7 -0
- package/dist/relay-client.d.ts.map +1 -1
- package/dist/relay-client.js +87 -4
- package/dist/relay-client.js.map +1 -1
- package/dist/relay-manager.d.ts +32 -0
- package/dist/relay-manager.d.ts.map +1 -0
- package/dist/relay-manager.js +168 -0
- package/dist/relay-manager.js.map +1 -0
- package/dist/relay-manager.test.d.ts +2 -0
- package/dist/relay-manager.test.d.ts.map +1 -0
- package/dist/relay-manager.test.js +120 -0
- package/dist/relay-manager.test.js.map +1 -0
- package/package.json +6 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"background-service.js","sourceRoot":"","sources":["../../src/installer/background-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"background-service.js","sourceRoot":"","sources":["../../src/installer/background-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface DevResetOptions {
|
|
2
|
+
/** Remove license.json — you'll need to sign in / enter key again. */
|
|
3
|
+
wipeLicense?: boolean;
|
|
4
|
+
/** Delete all of ~/.lockin (implies wipeLicense). */
|
|
5
|
+
wipeAll?: boolean;
|
|
6
|
+
/** Remove LockIn blocks from /etc/hosts. Default true. */
|
|
7
|
+
clearHosts?: boolean;
|
|
8
|
+
/** Remove LockIn from Claude Desktop config. Only with --full. */
|
|
9
|
+
clearClaudeDesktop?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** Stop any LockIn MCP HTTP server bound to the standard port range. */
|
|
12
|
+
export declare function killLockInHttpServers(): Promise<string[]>;
|
|
13
|
+
export declare function parseDevResetArgs(argv: string[]): DevResetOptions;
|
|
14
|
+
export declare function printDevResetHelp(): void;
|
|
15
|
+
export declare function runDevReset(options?: DevResetOptions): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=dev-reset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-reset.d.ts","sourceRoot":"","sources":["../../src/installer/dev-reset.ts"],"names":[],"mappings":"AAgCA,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,qDAAqD;IACrD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAmCD,wEAAwE;AACxE,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAyB/D;AAsED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,eAAe,CAiCjE;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAsBxC;AAED,wBAAsB,WAAW,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiE9E"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { access, mkdir, rm, unlink } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
import * as clack from "@clack/prompts";
|
|
6
|
+
import color from "picocolors";
|
|
7
|
+
import { syncHostsFile } from "../hosts-manager.js";
|
|
8
|
+
import { claudeDesktopConfigPath, LOCKIN_CLAUDE_MCP_SERVER_KEY, } from "./claude-desktop-config.js";
|
|
9
|
+
import { getDataDirPath } from "./data-dir.js";
|
|
10
|
+
import { uninstallLegacyTunnelLaunchAgents } from "./legacy-tunnels.js";
|
|
11
|
+
import { stopLockInMcpLaunchAgent } from "./mcp-cleanup.js";
|
|
12
|
+
import { DEFAULT_LOCKIN_MCP_PORT, fetchLockInHealth, stopLockInListenersOnPort, } from "./port.js";
|
|
13
|
+
const execFileAsync = promisify(execFile);
|
|
14
|
+
const LICENSE_FILE = "license.json";
|
|
15
|
+
const PARTIAL_RESET_FILES = [
|
|
16
|
+
"setup-manifest.json",
|
|
17
|
+
"relay-credentials.json",
|
|
18
|
+
"state.json",
|
|
19
|
+
"mcp.stdout.log",
|
|
20
|
+
"mcp.stderr.log",
|
|
21
|
+
"install.log",
|
|
22
|
+
];
|
|
23
|
+
function sleep(ms) {
|
|
24
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
25
|
+
}
|
|
26
|
+
async function pathExists(path) {
|
|
27
|
+
try {
|
|
28
|
+
await access(path);
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async function listenerPidsOnPort(port) {
|
|
36
|
+
const selfPid = process.pid;
|
|
37
|
+
try {
|
|
38
|
+
const { stdout } = await execFileAsync("lsof", [
|
|
39
|
+
"-nP",
|
|
40
|
+
`-iTCP:${port}`,
|
|
41
|
+
"-sTCP:LISTEN",
|
|
42
|
+
"-t",
|
|
43
|
+
]);
|
|
44
|
+
return stdout
|
|
45
|
+
.trim()
|
|
46
|
+
.split("\n")
|
|
47
|
+
.filter(Boolean)
|
|
48
|
+
.map((value) => Number(value))
|
|
49
|
+
.filter((pid) => Number.isFinite(pid) && pid > 0 && pid !== selfPid);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** Stop any LockIn MCP HTTP server bound to the standard port range. */
|
|
56
|
+
export async function killLockInHttpServers() {
|
|
57
|
+
const killed = [];
|
|
58
|
+
for (let offset = 0; offset < 20; offset += 1) {
|
|
59
|
+
const port = DEFAULT_LOCKIN_MCP_PORT + offset;
|
|
60
|
+
if (!(await fetchLockInHealth(port))) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const listenerPids = await listenerPidsOnPort(port);
|
|
64
|
+
if (listenerPids.length === 0) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
for (const pid of listenerPids) {
|
|
68
|
+
killed.push(`pid ${pid} (port ${port})`);
|
|
69
|
+
}
|
|
70
|
+
await stopLockInListenersOnPort(port);
|
|
71
|
+
}
|
|
72
|
+
if (killed.length > 0) {
|
|
73
|
+
await sleep(600);
|
|
74
|
+
}
|
|
75
|
+
return killed;
|
|
76
|
+
}
|
|
77
|
+
async function removeClaudeDesktopEntry() {
|
|
78
|
+
const configPath = claudeDesktopConfigPath();
|
|
79
|
+
if (!(await pathExists(configPath))) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
const { readFile, writeFile } = await import("node:fs/promises");
|
|
83
|
+
const raw = await readFile(configPath, "utf8");
|
|
84
|
+
const config = JSON.parse(raw);
|
|
85
|
+
const servers = config.mcpServers && typeof config.mcpServers === "object"
|
|
86
|
+
? config.mcpServers
|
|
87
|
+
: null;
|
|
88
|
+
if (!servers || !(LOCKIN_CLAUDE_MCP_SERVER_KEY in servers)) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
delete servers[LOCKIN_CLAUDE_MCP_SERVER_KEY];
|
|
92
|
+
config.mcpServers = servers;
|
|
93
|
+
await writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`);
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
async function wipeDataDir(options) {
|
|
97
|
+
const dataDir = getDataDirPath();
|
|
98
|
+
const removed = [];
|
|
99
|
+
if (options.wipeAll) {
|
|
100
|
+
if (await pathExists(dataDir)) {
|
|
101
|
+
await rm(dataDir, { recursive: true, force: true });
|
|
102
|
+
removed.push(dataDir);
|
|
103
|
+
}
|
|
104
|
+
await mkdir(dataDir, { recursive: true, mode: 0o700 });
|
|
105
|
+
return removed;
|
|
106
|
+
}
|
|
107
|
+
for (const name of PARTIAL_RESET_FILES) {
|
|
108
|
+
const path = join(dataDir, name);
|
|
109
|
+
if (await pathExists(path)) {
|
|
110
|
+
await unlink(path);
|
|
111
|
+
removed.push(path);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (options.wipeLicense) {
|
|
115
|
+
const licensePath = join(dataDir, LICENSE_FILE);
|
|
116
|
+
if (await pathExists(licensePath)) {
|
|
117
|
+
await unlink(licensePath);
|
|
118
|
+
removed.push(licensePath);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return removed;
|
|
122
|
+
}
|
|
123
|
+
async function removeHostsSudoersHint() {
|
|
124
|
+
const sudoersPath = "/etc/sudoers.d/lockin-mcp-hosts";
|
|
125
|
+
if (process.platform !== "darwin" || !(await pathExists(sudoersPath))) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
clack.log.info(color.dim(`Optional: remove passwordless hosts sudo — sudo rm ${sudoersPath}`));
|
|
129
|
+
}
|
|
130
|
+
export function parseDevResetArgs(argv) {
|
|
131
|
+
const options = {
|
|
132
|
+
clearHosts: true,
|
|
133
|
+
};
|
|
134
|
+
for (const arg of argv) {
|
|
135
|
+
switch (arg) {
|
|
136
|
+
case "--full":
|
|
137
|
+
options.wipeAll = true;
|
|
138
|
+
options.wipeLicense = true;
|
|
139
|
+
options.clearClaudeDesktop = true;
|
|
140
|
+
break;
|
|
141
|
+
case "--wipe-license":
|
|
142
|
+
options.wipeLicense = true;
|
|
143
|
+
break;
|
|
144
|
+
case "--no-hosts":
|
|
145
|
+
options.clearHosts = false;
|
|
146
|
+
break;
|
|
147
|
+
case "--help":
|
|
148
|
+
case "-h":
|
|
149
|
+
printDevResetHelp();
|
|
150
|
+
process.exit(0);
|
|
151
|
+
break;
|
|
152
|
+
default:
|
|
153
|
+
throw new Error(`Unknown option: ${arg}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (options.wipeAll) {
|
|
157
|
+
options.wipeLicense = true;
|
|
158
|
+
}
|
|
159
|
+
return options;
|
|
160
|
+
}
|
|
161
|
+
export function printDevResetHelp() {
|
|
162
|
+
console.log(`\
|
|
163
|
+
LockIn MCP — developer reset
|
|
164
|
+
|
|
165
|
+
Stops background daemons and dev servers, then wipes local install state so
|
|
166
|
+
the next install behaves like a fresh user machine.
|
|
167
|
+
|
|
168
|
+
Usage:
|
|
169
|
+
npx lockin-mcp dev-reset [options]
|
|
170
|
+
npm run dev:reset
|
|
171
|
+
|
|
172
|
+
Options:
|
|
173
|
+
--full Delete all of ~/.lockin including license (true fresh user)
|
|
174
|
+
--wipe-license Also remove license.json (re-auth on next install)
|
|
175
|
+
--no-hosts Leave /etc/hosts unchanged
|
|
176
|
+
-h, --help Show this help
|
|
177
|
+
|
|
178
|
+
Workflow:
|
|
179
|
+
npm run install:fresh # reset + wipe license + install (new-user flow)
|
|
180
|
+
npm run install:fresh:full # full ~/.lockin wipe + Claude Desktop + install
|
|
181
|
+
npm run dev:reset # reset relay/state only (keeps license for fast iteration)
|
|
182
|
+
`);
|
|
183
|
+
}
|
|
184
|
+
export async function runDevReset(options = {}) {
|
|
185
|
+
const clearHosts = options.clearHosts !== false;
|
|
186
|
+
clack.intro(color.bold("LockIn developer reset"));
|
|
187
|
+
const killed = await killLockInHttpServers();
|
|
188
|
+
if (killed.length > 0) {
|
|
189
|
+
clack.log.success(`Stopped LockIn HTTP server(s): ${killed.join(", ")}`);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
clack.log.info("No LockIn HTTP servers found on ports 3847–3866");
|
|
193
|
+
}
|
|
194
|
+
await uninstallLegacyTunnelLaunchAgents();
|
|
195
|
+
const stoppedAgent = await stopLockInMcpLaunchAgent();
|
|
196
|
+
if (stoppedAgent) {
|
|
197
|
+
clack.log.success("Stopped com.lockin.mcp LaunchAgent");
|
|
198
|
+
}
|
|
199
|
+
const removedPaths = await wipeDataDir(options);
|
|
200
|
+
if (removedPaths.length > 0) {
|
|
201
|
+
clack.log.success(options.wipeAll
|
|
202
|
+
? `Removed ${color.cyan("~/.lockin")} and recreated empty directory`
|
|
203
|
+
: `Removed ${removedPaths.length} file(s) from ${color.cyan("~/.lockin")}`);
|
|
204
|
+
}
|
|
205
|
+
if (options.clearClaudeDesktop) {
|
|
206
|
+
const cleared = await removeClaudeDesktopEntry();
|
|
207
|
+
if (cleared) {
|
|
208
|
+
clack.log.success("Removed LockIn from Claude Desktop config");
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (clearHosts) {
|
|
212
|
+
try {
|
|
213
|
+
const sync = await syncHostsFile([]);
|
|
214
|
+
if (sync.method === "unchanged") {
|
|
215
|
+
clack.log.info("Hosts file had no LockIn entries");
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
clack.log.success(`Cleared LockIn entries from /etc/hosts (${sync.method})`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
223
|
+
clack.log.warn(`Could not clear hosts file: ${message}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
await removeHostsSudoersHint();
|
|
227
|
+
const licenseNote = options.wipeAll || options.wipeLicense
|
|
228
|
+
? color.dim("License removed — install will prompt for sign-in or key.")
|
|
229
|
+
: color.dim("License kept — use --wipe-license or install:fresh for a new-user flow.");
|
|
230
|
+
clack.outro([
|
|
231
|
+
"Ready for a clean install.",
|
|
232
|
+
licenseNote,
|
|
233
|
+
"",
|
|
234
|
+
` ${color.cyan("npm run install:local")} — install from this repo`,
|
|
235
|
+
` ${color.cyan("npm run install:prod")} — install against production`,
|
|
236
|
+
` ${color.cyan("npx lockin-mcp install")} — install published package`,
|
|
237
|
+
].join("\n"));
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=dev-reset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-reset.js","sourceRoot":"","sources":["../../src/installer/dev-reset.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-reset.test.d.ts","sourceRoot":"","sources":["../../src/installer/dev-reset.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { parseDevResetArgs } from "./dev-reset.js";
|
|
3
|
+
describe("parseDevResetArgs", () => {
|
|
4
|
+
it("defaults to partial reset with hosts cleanup", () => {
|
|
5
|
+
expect(parseDevResetArgs([])).toEqual({
|
|
6
|
+
clearHosts: true,
|
|
7
|
+
});
|
|
8
|
+
});
|
|
9
|
+
it("enables full wipe flags", () => {
|
|
10
|
+
expect(parseDevResetArgs(["--full"])).toEqual({
|
|
11
|
+
wipeAll: true,
|
|
12
|
+
wipeLicense: true,
|
|
13
|
+
clearHosts: true,
|
|
14
|
+
clearClaudeDesktop: true,
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
it("can skip hosts cleanup", () => {
|
|
18
|
+
expect(parseDevResetArgs(["--no-hosts"])).toEqual({
|
|
19
|
+
clearHosts: false,
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=dev-reset.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-reset.test.js","sourceRoot":"","sources":["../../src/installer/dev-reset.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YACpC,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC5C,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,IAAI;YACjB,UAAU,EAAE,IAAI;YAChB,kBAAkB,EAAE,IAAI;SACzB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,iBAAiB,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAChD,UAAU,EAAE,KAAK;SAClB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/installer/port.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
export declare const DEFAULT_LOCKIN_MCP_PORT = 3847;
|
|
2
|
+
export interface LockInHealthSnapshot {
|
|
3
|
+
service: string;
|
|
4
|
+
relayConnected: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function fetchLockInHealthSnapshot(port: number): Promise<LockInHealthSnapshot | null>;
|
|
2
7
|
export declare function fetchLockInHealth(port: number): Promise<boolean>;
|
|
8
|
+
/** Stop a LockIn MCP listener so launchd or a fresh install can recover the port. */
|
|
9
|
+
export declare function stopLockInListenersOnPort(port: number): Promise<void>;
|
|
10
|
+
export declare function waitForLocalRelayHealth(port: number, attempts?: number, delayMs?: number): Promise<LockInHealthSnapshot>;
|
|
3
11
|
export declare function isPortAvailable(port: number): Promise<boolean>;
|
|
4
12
|
export declare function describePortConflict(port: number): Promise<string | null>;
|
|
5
13
|
export declare function resolveMcpPort(preferred: number): Promise<number>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../src/installer/port.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../src/installer/port.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAE5C,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAsBtC;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEtE;AAuBD,qFAAqF;AACrF,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B3E;AAED,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,MAAM,EACZ,QAAQ,SAAK,EACb,OAAO,SAAM,GACZ,OAAO,CAAC,oBAAoB,CAAC,CAY/B;AAMD,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASpE;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuB/E;AAED,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BvE"}
|
package/dist/installer/port.js
CHANGED
|
@@ -1,20 +1,92 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
1
2
|
import { createServer } from "node:net";
|
|
3
|
+
import { promisify } from "node:util";
|
|
2
4
|
import { localHttpRequest } from "../local-http.js";
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
3
6
|
export const DEFAULT_LOCKIN_MCP_PORT = 3847;
|
|
4
|
-
export async function
|
|
7
|
+
export async function fetchLockInHealthSnapshot(port) {
|
|
5
8
|
try {
|
|
6
9
|
const response = await localHttpRequest(`http://127.0.0.1:${port}/health`, {
|
|
7
10
|
timeoutMs: 2000,
|
|
8
11
|
});
|
|
9
12
|
if (!response.ok) {
|
|
10
|
-
return
|
|
13
|
+
return null;
|
|
11
14
|
}
|
|
12
15
|
const body = (await response.json());
|
|
13
|
-
|
|
16
|
+
if (body.service !== "lockin-mcp") {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
service: body.service,
|
|
21
|
+
relayConnected: body.relay?.connected === true,
|
|
22
|
+
};
|
|
14
23
|
}
|
|
15
24
|
catch {
|
|
16
|
-
return
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export async function fetchLockInHealth(port) {
|
|
29
|
+
return (await fetchLockInHealthSnapshot(port)) !== null;
|
|
30
|
+
}
|
|
31
|
+
function sleep(ms) {
|
|
32
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
33
|
+
}
|
|
34
|
+
async function findListenerPids(port) {
|
|
35
|
+
try {
|
|
36
|
+
const { stdout } = await execFileAsync("lsof", [
|
|
37
|
+
"-nP",
|
|
38
|
+
`-iTCP:${port}`,
|
|
39
|
+
"-sTCP:LISTEN",
|
|
40
|
+
"-t",
|
|
41
|
+
]);
|
|
42
|
+
return stdout
|
|
43
|
+
.split("\n")
|
|
44
|
+
.map((line) => Number(line.trim()))
|
|
45
|
+
.filter((pid) => Number.isFinite(pid) && pid > 0);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Stop a LockIn MCP listener so launchd or a fresh install can recover the port. */
|
|
52
|
+
export async function stopLockInListenersOnPort(port) {
|
|
53
|
+
const pids = await findListenerPids(port);
|
|
54
|
+
for (const pid of pids) {
|
|
55
|
+
try {
|
|
56
|
+
process.kill(pid, "SIGTERM");
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// already exited
|
|
60
|
+
}
|
|
17
61
|
}
|
|
62
|
+
for (let attempt = 0; attempt < 10; attempt += 1) {
|
|
63
|
+
if (await isPortAvailable(port)) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
await sleep(300);
|
|
67
|
+
}
|
|
68
|
+
for (const pid of await findListenerPids(port)) {
|
|
69
|
+
try {
|
|
70
|
+
process.kill(pid, "SIGKILL");
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// already exited
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
await sleep(300);
|
|
77
|
+
}
|
|
78
|
+
export async function waitForLocalRelayHealth(port, attempts = 40, delayMs = 500) {
|
|
79
|
+
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
80
|
+
const snapshot = await fetchLockInHealthSnapshot(port);
|
|
81
|
+
if (snapshot?.relayConnected) {
|
|
82
|
+
return snapshot;
|
|
83
|
+
}
|
|
84
|
+
await sleep(delayMs);
|
|
85
|
+
}
|
|
86
|
+
throw new Error(`LockIn MCP on port ${port} never connected to relay — check ${getDataDirHint()}/mcp.stderr.log`);
|
|
87
|
+
}
|
|
88
|
+
function getDataDirHint() {
|
|
89
|
+
return process.platform === "win32" ? "%USERPROFILE%\\.lockin" : "~/.lockin";
|
|
18
90
|
}
|
|
19
91
|
export async function isPortAvailable(port) {
|
|
20
92
|
return new Promise((resolve) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"port.js","sourceRoot":"","sources":["../../src/installer/port.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"port.js","sourceRoot":"","sources":["../../src/installer/port.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port.test.d.ts","sourceRoot":"","sources":["../../src/installer/port.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, expect, it, vi, afterEach } from "vitest";
|
|
2
|
+
import { fetchLockInHealthSnapshot, waitForLocalRelayHealth, } from "./port.js";
|
|
3
|
+
vi.mock("../local-http.js", () => ({
|
|
4
|
+
localHttpRequest: vi.fn(),
|
|
5
|
+
}));
|
|
6
|
+
import { localHttpRequest } from "../local-http.js";
|
|
7
|
+
function mockHealthResponse(body) {
|
|
8
|
+
return {
|
|
9
|
+
ok: true,
|
|
10
|
+
status: 200,
|
|
11
|
+
headers: {},
|
|
12
|
+
text: async () => JSON.stringify(body),
|
|
13
|
+
json: async () => body,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
describe("fetchLockInHealthSnapshot", () => {
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
vi.mocked(localHttpRequest).mockReset();
|
|
19
|
+
});
|
|
20
|
+
it("returns relay connection state from /health", async () => {
|
|
21
|
+
vi.mocked(localHttpRequest).mockResolvedValue(mockHealthResponse({
|
|
22
|
+
service: "lockin-mcp",
|
|
23
|
+
relay: { connected: true },
|
|
24
|
+
}));
|
|
25
|
+
await expect(fetchLockInHealthSnapshot(3848)).resolves.toEqual({
|
|
26
|
+
service: "lockin-mcp",
|
|
27
|
+
relayConnected: true,
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
it("returns null for non-lockin listeners", async () => {
|
|
31
|
+
vi.mocked(localHttpRequest).mockResolvedValue(mockHealthResponse({ service: "other-app" }));
|
|
32
|
+
await expect(fetchLockInHealthSnapshot(3848)).resolves.toBeNull();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe("waitForLocalRelayHealth", () => {
|
|
36
|
+
afterEach(() => {
|
|
37
|
+
vi.mocked(localHttpRequest).mockReset();
|
|
38
|
+
});
|
|
39
|
+
it("waits until relay.connected is true", async () => {
|
|
40
|
+
vi.mocked(localHttpRequest)
|
|
41
|
+
.mockResolvedValueOnce(mockHealthResponse({
|
|
42
|
+
service: "lockin-mcp",
|
|
43
|
+
relay: { connected: false },
|
|
44
|
+
}))
|
|
45
|
+
.mockResolvedValueOnce(mockHealthResponse({
|
|
46
|
+
service: "lockin-mcp",
|
|
47
|
+
relay: { connected: true },
|
|
48
|
+
}));
|
|
49
|
+
await expect(waitForLocalRelayHealth(3848, 5, 1)).resolves.toEqual({
|
|
50
|
+
service: "lockin-mcp",
|
|
51
|
+
relayConnected: true,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=port.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port.test.js","sourceRoot":"","sources":["../../src/installer/port.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAE7D,OAAO,EACL,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AAEnB,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,CAAC;IACjC,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE;CAC1B,CAAC,CAAC,CAAC;AAEJ,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,SAAS,kBAAkB,CAAC,IAAa;IACvC,OAAO;QACL,EAAE,EAAE,IAAI;QACR,MAAM,EAAE,GAAG;QACX,OAAO,EAAE,EAAE;QACX,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QACtC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;KACvB,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,SAAS,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAC3C,kBAAkB,CAAC;YACjB,OAAO,EAAE,YAAY;YACrB,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE;SAC3B,CAAC,CACH,CAAC;QAEF,MAAM,MAAM,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;YAC7D,OAAO,EAAE,YAAY;YACrB,cAAc,EAAE,IAAI;SACrB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAC3C,kBAAkB,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAC7C,CAAC;QAEF,MAAM,MAAM,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IACpE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,SAAS,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC;aACxB,qBAAqB,CACpB,kBAAkB,CAAC;YACjB,OAAO,EAAE,YAAY;YACrB,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE;SAC5B,CAAC,CACH;aACA,qBAAqB,CACpB,kBAAkB,CAAC;YACjB,OAAO,EAAE,YAAY;YACrB,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE;SAC3B,CAAC,CACH,CAAC;QAEJ,MAAM,MAAM,CACV,uBAAuB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CACpC,CAAC,QAAQ,CAAC,OAAO,CAAC;YACjB,OAAO,EAAE,YAAY;YACrB,cAAc,EAAE,IAAI;SACrB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/installer/run.js
CHANGED
|
@@ -9,9 +9,9 @@ import { canWriteHostsFile } from "../hosts-manager.js";
|
|
|
9
9
|
import { verifyLicenseInfo } from "../license-check.js";
|
|
10
10
|
import { resolveLicense } from "./license.js";
|
|
11
11
|
import { detectPlatform, ensureNodeVersion } from "./platform.js";
|
|
12
|
-
import { describePortConflict, resolveMcpPort } from "./port.js";
|
|
12
|
+
import { describePortConflict, resolveMcpPort, stopLockInListenersOnPort, fetchLockInHealth } from "./port.js";
|
|
13
13
|
import { buildPokeUrls, POKE_LOCKIN_RECIPE_URL } from "./poke.js";
|
|
14
|
-
import { promptConnectAgent, promptBackgroundService,
|
|
14
|
+
import { promptConnectAgent, promptBackgroundService, handoffToBackgroundService } from "./agents.js";
|
|
15
15
|
import { promptInstallHostsSudoers } from "./hosts-sudo.js";
|
|
16
16
|
import { uninstallLegacyTunnelLaunchAgents } from "./legacy-tunnels.js";
|
|
17
17
|
import { stopLockInMcpLaunchAgent } from "./mcp-cleanup.js";
|
|
@@ -167,6 +167,10 @@ async function runInstallerInner(argv) {
|
|
|
167
167
|
if (stoppedBackground) {
|
|
168
168
|
clack.log.info("Stopped previous LockIn session for a clean setup.");
|
|
169
169
|
}
|
|
170
|
+
if (await fetchLockInHealth(options.port)) {
|
|
171
|
+
await stopLockInListenersOnPort(options.port);
|
|
172
|
+
clack.log.info("Cleared previous LockIn HTTP server on this port.");
|
|
173
|
+
}
|
|
170
174
|
const portConflict = await describePortConflict(options.port);
|
|
171
175
|
if (portConflict) {
|
|
172
176
|
const resolvedPort = await resolveMcpPort(options.port);
|
|
@@ -294,7 +298,7 @@ async function runInstallerInner(argv) {
|
|
|
294
298
|
const hasRemoteRelay = !options.skipTunnel && remoteMcpUrl.startsWith("https://");
|
|
295
299
|
const serverEntry = join(dirname(fileURLToPath(import.meta.url)), "..", "index.js");
|
|
296
300
|
if (!options.nonInteractive) {
|
|
297
|
-
const
|
|
301
|
+
const wantsBackground = await promptBackgroundService({
|
|
298
302
|
port: options.port,
|
|
299
303
|
authToken: mcpAuthToken,
|
|
300
304
|
serverEntry,
|
|
@@ -302,9 +306,21 @@ async function runInstallerInner(argv) {
|
|
|
302
306
|
deviceId: relayCredentials?.deviceId,
|
|
303
307
|
relayDeviceToken: relayCredentials?.relayDeviceToken,
|
|
304
308
|
});
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
await
|
|
309
|
+
let installedBackground = false;
|
|
310
|
+
if (wantsBackground) {
|
|
311
|
+
await handoffToBackgroundService({
|
|
312
|
+
mcpProcess,
|
|
313
|
+
port: options.port,
|
|
314
|
+
service: {
|
|
315
|
+
port: options.port,
|
|
316
|
+
authToken: mcpAuthToken,
|
|
317
|
+
serverEntry,
|
|
318
|
+
relayUrl: relayCredentials?.relayConnectUrl ?? relayCredentials?.relayUrl,
|
|
319
|
+
deviceId: relayCredentials?.deviceId,
|
|
320
|
+
relayDeviceToken: relayCredentials?.relayDeviceToken,
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
installedBackground = true;
|
|
308
324
|
}
|
|
309
325
|
if (hasRemoteRelay) {
|
|
310
326
|
await promptConnectAgent({
|
|
@@ -325,20 +341,20 @@ async function runInstallerInner(argv) {
|
|
|
325
341
|
}
|
|
326
342
|
}
|
|
327
343
|
else if (relayCredentials) {
|
|
328
|
-
|
|
344
|
+
await handoffToBackgroundService({
|
|
345
|
+
mcpProcess,
|
|
329
346
|
port: options.port,
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
347
|
+
service: {
|
|
348
|
+
port: options.port,
|
|
349
|
+
authToken: mcpAuthToken,
|
|
350
|
+
serverEntry,
|
|
351
|
+
relayUrl: relayCredentials.relayConnectUrl ?? relayCredentials.relayUrl,
|
|
352
|
+
deviceId: relayCredentials.deviceId,
|
|
353
|
+
relayDeviceToken: relayCredentials.relayDeviceToken,
|
|
354
|
+
},
|
|
335
355
|
});
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
await waitForHttp(`${localMcpUrl}/health`, 20, 500);
|
|
339
|
-
clack.outro(color.dim(`LockIn MCP runs in the background on port ${options.port}. Remote URL: ${remoteMcpUrl}`));
|
|
340
|
-
process.exit(0);
|
|
341
|
-
}
|
|
356
|
+
clack.outro(color.dim(`LockIn MCP runs in the background on port ${options.port}. Remote URL: ${remoteMcpUrl}`));
|
|
357
|
+
process.exit(0);
|
|
342
358
|
}
|
|
343
359
|
if (hasRemoteRelay) {
|
|
344
360
|
clack.outro(color.dim("LockIn is running. Turn on background mode next time to close this window."));
|