breakpoint-mcp 1.85.0 → 1.86.0
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/annotations.js +3 -3
- package/dist/annotations.js.map +1 -1
- package/dist/bridge.js +27 -1
- package/dist/bridge.js.map +1 -1
- package/dist/capabilities.js +1 -1
- package/dist/cli/doctor.js +65 -6
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/init.js +1 -1
- package/dist/cli/tools.js +2 -2
- package/dist/index.js +11 -5
- package/dist/index.js.map +1 -1
- package/dist/paths.js +8 -1
- package/dist/paths.js.map +1 -1
- package/dist/peers.js +1 -2
- package/dist/peers.js.map +1 -1
- package/dist/port-holder.js +235 -0
- package/dist/port-holder.js.map +1 -0
- package/dist/ports.js +117 -1
- package/dist/ports.js.map +1 -1
- package/dist/recipes.js +1 -1
- package/dist/schemas.js +18 -0
- package/dist/schemas.js.map +1 -1
- package/dist/tool-census.js +2 -2
- package/dist/tools/cli.js +18 -2
- package/dist/tools/cli.js.map +1 -1
- package/dist/tools/csdap.js +3 -1
- package/dist/tools/csdap.js.map +1 -1
- package/dist/tools/dap.js +3 -1
- package/dist/tools/dap.js.map +1 -1
- package/dist/tools/lsp.js +16 -4
- package/dist/tools/lsp.js.map +1 -1
- package/dist/tools/processes.js +7 -2
- package/dist/tools/processes.js.map +1 -1
- package/dist/tools/vcs.js +87 -7
- package/dist/tools/vcs.js.map +1 -1
- package/package.json +1 -1
package/dist/paths.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAS,EAAE,WAAmB;IACrD,IAAI,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACpF,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,SAAS,CAAC,CAAS,EAAE,WAAmB;IACtD,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AACtD,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAwBD,SAAS,MAAM,CAAC,IAAY,EAAE,OAAe;IAC3C,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,IAAa,EAAE,IAAI,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"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"}
|
package/dist/peers.js
CHANGED
|
@@ -18,7 +18,6 @@ import { describeExit, peerExitRemedy, readinessHint, readinessRemedy } from "./
|
|
|
18
18
|
export const MAX_PEERS = 4;
|
|
19
19
|
/** How far above the default runtime port the allocator will scan. */
|
|
20
20
|
const PORT_SCAN_SPAN = 200;
|
|
21
|
-
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
22
21
|
export class PeerRegistry {
|
|
23
22
|
cfg;
|
|
24
23
|
/** Peers get their OWN process registry, so peer ids and `godot_run_managed`
|
|
@@ -183,7 +182,7 @@ export class PeerRegistry {
|
|
|
183
182
|
};
|
|
184
183
|
if (opts.role)
|
|
185
184
|
env.BREAKPOINT_PEER_ROLE = opts.role;
|
|
186
|
-
const managed = await this.procs.run(this.cfg, extraArgs, env);
|
|
185
|
+
const managed = await this.procs.run(this.cfg, extraArgs, env, { tool: "runtime_spawn_peers", id, port });
|
|
187
186
|
// 🔴 282 — A PEER THAT NEVER STARTED IS REPORTED, NOT REGISTERED. Before
|
|
188
187
|
// this, a wrong `GODOT_BIN` took the whole host down on the first peer;
|
|
189
188
|
// `spawnGuarded` now hands back the refusal, and a peer with no process is
|
package/dist/peers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"peers.js","sourceRoot":"","sources":["../src/peers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,eAAe,EAAuB,MAAM,iBAAiB,CAAC;AAiDpH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAE3B,sEAAsE;AACtE,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B,MAAM,
|
|
1
|
+
{"version":3,"file":"peers.js","sourceRoot":"","sources":["../src/peers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
/** Measured at 29 ms on the Mac; the ceiling exists for a machine with a hung network mount. */
|
|
4
|
+
const LOOKUP_TIMEOUT_MS = 2000;
|
|
5
|
+
/** The one invocation. `+c 0` lifts lsof's nine-character truncation of the program name. */
|
|
6
|
+
export function lsofArgs(port) {
|
|
7
|
+
return ["-nP", `-iTCP:${port}`, "-sTCP:LISTEN", "-Fpcn", "+c", "0"];
|
|
8
|
+
}
|
|
9
|
+
const runExec = (file, args, timeoutMs) => new Promise((resolve) => {
|
|
10
|
+
execFile(file, [...args], { timeout: timeoutMs, encoding: "utf8", maxBuffer: 1024 * 1024 }, (err, stdout) => {
|
|
11
|
+
if (!err) {
|
|
12
|
+
resolve({ code: 0, timedOut: false, stdout });
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const e = err;
|
|
16
|
+
resolve({ code: e.code ?? null, timedOut: e.killed === true, stdout: typeof stdout === "string" ? stdout : "" });
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
/** Does `host` name this machine's loopback — the only table lsof can read for it? */
|
|
20
|
+
export function isLoopbackHost(host) {
|
|
21
|
+
const h = host.trim().toLowerCase();
|
|
22
|
+
return h === "localhost" || h === "::1" || h === "[::1]" || /^127(\.\d{1,3}){3}$/.test(h);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* lsof escapes a byte it will not print as `\xNN` — measured on the Mac as
|
|
26
|
+
* `ROLI\x20Hardware\x20Driver`. A remedy that names the program should name it as a person
|
|
27
|
+
* sees it in Activity Monitor.
|
|
28
|
+
*/
|
|
29
|
+
function decodeLsofName(s) {
|
|
30
|
+
return s.replace(/\\x([0-9a-fA-F]{2})/g, (_m, hex) => String.fromCharCode(Number.parseInt(hex, 16)));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Parse `-Fpcn` output: a `p` line opens a process, `c` names it, and each `n` is one of its
|
|
34
|
+
* sockets. Every other field letter is ignored — macOS emits an `f` line per socket and Linux,
|
|
35
|
+
* measured the same day, does not.
|
|
36
|
+
*/
|
|
37
|
+
export function parseLsof(stdout) {
|
|
38
|
+
const out = [];
|
|
39
|
+
let pid = null;
|
|
40
|
+
let command = "";
|
|
41
|
+
for (const raw of stdout.split("\n")) {
|
|
42
|
+
const line = raw.replace(/\r$/, "");
|
|
43
|
+
if (line.length === 0)
|
|
44
|
+
continue;
|
|
45
|
+
const value = line.slice(1);
|
|
46
|
+
switch (line[0]) {
|
|
47
|
+
case "p": {
|
|
48
|
+
const n = Number(value);
|
|
49
|
+
pid = Number.isInteger(n) && n > 0 ? n : null;
|
|
50
|
+
command = "";
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
case "c":
|
|
54
|
+
command = decodeLsofName(value);
|
|
55
|
+
break;
|
|
56
|
+
case "n":
|
|
57
|
+
if (pid !== null && value.length > 0)
|
|
58
|
+
out.push({ pid, command, address: value });
|
|
59
|
+
break;
|
|
60
|
+
default:
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
/** Ask this machine's listener table who is listening on `port`. Never throws. */
|
|
67
|
+
export async function readHolder(host, port, opts = {}) {
|
|
68
|
+
if ((opts.platform ?? process.platform) === "win32") {
|
|
69
|
+
return { kind: "unavailable", reason: "no listener lookup is implemented on Windows" };
|
|
70
|
+
}
|
|
71
|
+
if (!isLoopbackHost(host)) {
|
|
72
|
+
return { kind: "unavailable", reason: `${host} is not this machine's loopback, so its listeners cannot be read from here` };
|
|
73
|
+
}
|
|
74
|
+
const timeoutMs = opts.timeoutMs ?? LOOKUP_TIMEOUT_MS;
|
|
75
|
+
const r = await (opts.exec ?? runExec)("lsof", lsofArgs(port), timeoutMs);
|
|
76
|
+
if (r.code === "ENOENT")
|
|
77
|
+
return { kind: "unavailable", reason: "lsof is not installed" };
|
|
78
|
+
if (r.timedOut)
|
|
79
|
+
return { kind: "unavailable", reason: `lsof did not answer within ${timeoutMs} ms` };
|
|
80
|
+
if (r.code === 1 && r.stdout.trim() === "")
|
|
81
|
+
return { kind: "none_visible" };
|
|
82
|
+
if (r.code !== 0)
|
|
83
|
+
return { kind: "unavailable", reason: `lsof exited ${String(r.code)}` };
|
|
84
|
+
const listeners = parseLsof(r.stdout);
|
|
85
|
+
if (listeners.length === 0)
|
|
86
|
+
return { kind: "unavailable", reason: "lsof printed nothing this reader could parse" };
|
|
87
|
+
return { kind: "found", listeners };
|
|
88
|
+
}
|
|
89
|
+
const owned = new Map();
|
|
90
|
+
/** Record that this server started `child`. A child that never got a pid records nothing. */
|
|
91
|
+
export function noteOwned(child, owner) {
|
|
92
|
+
const pid = child?.pid;
|
|
93
|
+
if (!child || typeof pid !== "number")
|
|
94
|
+
return;
|
|
95
|
+
owned.set(pid, owner);
|
|
96
|
+
child.once("exit", () => {
|
|
97
|
+
if (owned.get(pid) === owner)
|
|
98
|
+
owned.delete(pid);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/** The live peers this server spawned, with the port each was given. */
|
|
102
|
+
export function ownedPeers() {
|
|
103
|
+
const out = [];
|
|
104
|
+
for (const [pid, o] of owned)
|
|
105
|
+
if (o.tool === "runtime_spawn_peers")
|
|
106
|
+
out.push({ id: o.id, port: o.port, pid });
|
|
107
|
+
return out.sort((a, b) => a.port - b.port);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Is `command` a Godot binary? The name contains "godot" (`Godot`, `godot`,
|
|
111
|
+
* `Godot_v4.4-stable_linux.x86_64`, whose 15-byte Linux `comm` is `Godot_v4.4-stab`), or it is
|
|
112
|
+
* exactly the basename `GODOT_BIN` names — the one case a renamed build is still recognised.
|
|
113
|
+
*/
|
|
114
|
+
function looksLikeGodot(command, godotBin) {
|
|
115
|
+
const bin = path.basename(godotBin).replace(/\.exe$/i, "");
|
|
116
|
+
return /godot/i.test(command) || (bin.length > 0 && command === bin);
|
|
117
|
+
}
|
|
118
|
+
/** Whose is this listener — ours by ledger, then this very process, then Godot-or-not by name. */
|
|
119
|
+
export function attribute(l, godotBin, selfPid = process.pid) {
|
|
120
|
+
const o = owned.get(l.pid);
|
|
121
|
+
if (o?.tool === "godot_run_managed")
|
|
122
|
+
return { kind: "godot_run_managed", id: o.id };
|
|
123
|
+
if (o?.tool === "runtime_spawn_peers")
|
|
124
|
+
return { kind: "runtime_spawn_peers", id: o.id };
|
|
125
|
+
if (o?.tool === "godot_run_project")
|
|
126
|
+
return { kind: "godot_run_project" };
|
|
127
|
+
if (l.pid === selfPid)
|
|
128
|
+
return { kind: "this_server" };
|
|
129
|
+
return looksLikeGodot(l.command, godotBin) ? { kind: "godot" } : { kind: "other" };
|
|
130
|
+
}
|
|
131
|
+
/** Fold listeners by pid — one process on `127.0.0.1` and `[::1]` is one holder, not two. */
|
|
132
|
+
export function foldHolders(listeners, godotBin, selfPid = process.pid) {
|
|
133
|
+
const byPid = new Map();
|
|
134
|
+
for (const l of listeners) {
|
|
135
|
+
const h = byPid.get(l.pid);
|
|
136
|
+
if (h) {
|
|
137
|
+
if (!h.addresses.includes(l.address))
|
|
138
|
+
h.addresses.push(l.address);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
byPid.set(l.pid, { pid: l.pid, command: l.command, addresses: [l.address], owner: attribute(l, godotBin, selfPid) });
|
|
142
|
+
}
|
|
143
|
+
return [...byPid.values()];
|
|
144
|
+
}
|
|
145
|
+
/** Read the table and attribute what it says. */
|
|
146
|
+
export async function whoHolds(host, port, godotBin, opts = {}) {
|
|
147
|
+
const r = await readHolder(host, port, opts);
|
|
148
|
+
if (r.kind !== "found")
|
|
149
|
+
return r;
|
|
150
|
+
return { kind: "found", holders: foldHolders(r.listeners, godotBin) };
|
|
151
|
+
}
|
|
152
|
+
// ── Sentences ───────────────────────────────────────────────────────────────────────────
|
|
153
|
+
/** `the game godot_run_managed started as "godot-2" (pid 4312, Godot, on 127.0.0.1:9081)` */
|
|
154
|
+
export function holderPhrase(h) {
|
|
155
|
+
const facts = `(pid ${h.pid}, ${h.command || "unnamed"}, on ${h.addresses.join(" and ")})`;
|
|
156
|
+
switch (h.owner.kind) {
|
|
157
|
+
case "godot_run_managed":
|
|
158
|
+
return `the game godot_run_managed started as "${h.owner.id}" ${facts}`;
|
|
159
|
+
case "runtime_spawn_peers":
|
|
160
|
+
return `peer "${h.owner.id}", which runtime_spawn_peers started ${facts}`;
|
|
161
|
+
case "godot_run_project":
|
|
162
|
+
return `a detached game godot_run_project started ${facts}`;
|
|
163
|
+
case "this_server":
|
|
164
|
+
return `this Breakpoint server's own process ${facts}`;
|
|
165
|
+
case "godot":
|
|
166
|
+
return `a Godot process this server did not start ${facts}`;
|
|
167
|
+
default:
|
|
168
|
+
return `a program that is not Godot ${facts}`;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/** `a; b` for several holders, the phrase for one. */
|
|
172
|
+
export function holdersPhrase(holders) {
|
|
173
|
+
return holders.map(holderPhrase).join("; ");
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* The stop that is certain to work, when this server knows one — `undefined` when the holder
|
|
177
|
+
* is not a process any tool here can stop. Only a ledger match earns a tool name: a Godot this
|
|
178
|
+
* server did not start may be a game, an editor, or a debugger-launched session, and naming a
|
|
179
|
+
* tool for it would be the guess `ports.ts` spent a paragraph refusing.
|
|
180
|
+
*/
|
|
181
|
+
export function certainStop(h) {
|
|
182
|
+
switch (h.owner.kind) {
|
|
183
|
+
case "godot_run_managed":
|
|
184
|
+
return `stop it with godot_stop, id "${h.owner.id}"`;
|
|
185
|
+
case "runtime_spawn_peers":
|
|
186
|
+
return `stop it with runtime_peer_stop, id "${h.owner.id}"`;
|
|
187
|
+
default:
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/** A short form for a row that is otherwise fine: `Godot, pid 511` / `3 processes`. */
|
|
192
|
+
export function holderBrief(holders) {
|
|
193
|
+
if (holders.length !== 1)
|
|
194
|
+
return `${holders.length} processes, pids ${holders.map((h) => h.pid).join(", ")}`;
|
|
195
|
+
const h = holders[0];
|
|
196
|
+
return `${h.command || "unnamed"}, pid ${h.pid}`;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* The silent-peer remedy with the holder named — `bridge.ts`'s sentence, which used to end in
|
|
200
|
+
* a Terminal command, finished by running it. `undefined` when the lookup could not answer,
|
|
201
|
+
* so the caller keeps the sentence it already had.
|
|
202
|
+
*
|
|
203
|
+
* 🔴 WRITTEN TO CHECK 28's GRAMMAR, AND THE FIRST DRAFT WAS NOT. It led with the diagnosis —
|
|
204
|
+
* *nothing on 127.0.0.1:9081 has ever spoken …* — and put the next action last, which is the
|
|
205
|
+
* order a person narrating the failure would use and the wrong order for a field whose whole
|
|
206
|
+
* job is the next action: the message beside it already says what failed. Each branch now
|
|
207
|
+
* opens with the one thing to do, and the diagnosis is the reason clause behind it.
|
|
208
|
+
*/
|
|
209
|
+
export function silentHolderRemedy(host, port, peerNoun, hostKnob, holder) {
|
|
210
|
+
if (holder.kind === "unavailable")
|
|
211
|
+
return undefined;
|
|
212
|
+
const where = `${host}:${port}`;
|
|
213
|
+
if (holder.kind === "none_visible") {
|
|
214
|
+
return `Set ${hostKnob} and its port knob to move this plane — ${where} never spoke the Breakpoint bridge protocol, and its holder belongs to another account, so no tool here can stop it.`;
|
|
215
|
+
}
|
|
216
|
+
const hs = holder.holders;
|
|
217
|
+
const who = holdersPhrase(hs);
|
|
218
|
+
const stop = hs.length === 1 ? stopCall(hs[0]) : undefined;
|
|
219
|
+
if (stop !== undefined) {
|
|
220
|
+
return `Call ${stop} to free ${where}, or set ${hostKnob} and its port knob — it is held by ${who}, which never spoke the Breakpoint bridge protocol, so ${peerNoun} is not what failed.`;
|
|
221
|
+
}
|
|
222
|
+
return `Set ${hostKnob} and its port knob to move this plane, or close what holds ${where}: ${who}. It never spoke the Breakpoint bridge protocol, so ${peerNoun} is not what failed.`;
|
|
223
|
+
}
|
|
224
|
+
/** `godot_stop with id "godot-2"` — the call-shaped half of `certainStop`, for a sentence that opens on the verb. */
|
|
225
|
+
function stopCall(h) {
|
|
226
|
+
switch (h.owner.kind) {
|
|
227
|
+
case "godot_run_managed":
|
|
228
|
+
return `godot_stop with id "${h.owner.id}"`;
|
|
229
|
+
case "runtime_spawn_peers":
|
|
230
|
+
return `runtime_peer_stop with id "${h.owner.id}"`;
|
|
231
|
+
default:
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=port-holder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-holder.js","sourceRoot":"","sources":["../src/port-holder.ts"],"names":[],"mappings":"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"}
|
package/dist/ports.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import net from "node:net";
|
|
2
|
+
import { certainStop, holderPhrase, holdersPhrase, isLoopbackHost, ownedPeers, whoHolds } from "./port-holder.js";
|
|
2
3
|
/**
|
|
3
4
|
* Loopback port probing, shared by the two callers that must not collide.
|
|
4
5
|
*
|
|
@@ -72,11 +73,24 @@ export function portFree(host, port) {
|
|
|
72
73
|
* whenever the holder was a managed child, which is the commonest case of all.
|
|
73
74
|
* Both variants now list every remedy with the condition under which it applies,
|
|
74
75
|
* and assert nothing about which one is live.
|
|
76
|
+
*
|
|
77
|
+
* 🆕 318 — THAT RULE STILL HOLDS FOR THE PROBE, AND THE PROBE IS NO LONGER THE ONLY READER.
|
|
78
|
+
* `holder`, when a caller passes it, is `port-holder.ts`'s reading of the kernel's listener
|
|
79
|
+
* table plus this server's own ledger of the children it started: a pid, a program name, and
|
|
80
|
+
* whether `godot_run_managed` or `runtime_spawn_peers` owns it. With that in hand the message
|
|
81
|
+
* names the holder and the one remedy that applies to it. Without it — lsof missing, a host
|
|
82
|
+
* that is not loopback, Windows — every character below is what shipped before.
|
|
75
83
|
*/
|
|
76
|
-
export function portConflictMessage(host, port, launcher = "run") {
|
|
84
|
+
export function portConflictMessage(host, port, launcher = "run", holder) {
|
|
77
85
|
const why = `${host}:${port} is already bound, so a game started now could not host the runtime bridge. ` +
|
|
78
86
|
`Its autoload would fail to listen and keep running anyway, and every runtime_* call would ` +
|
|
79
87
|
`silently address the process that already holds the port instead of the one you just started. `;
|
|
88
|
+
// 🆕 318 — WHEN THE HOLDER IS KNOWN, SAY WHICH REMEDY IS LIVE. Everything below this branch
|
|
89
|
+
// is the text that shipped, byte for byte, and it is still what a caller reads whenever
|
|
90
|
+
// the lookup could not answer (no lsof, a non-loopback host, Windows).
|
|
91
|
+
const known = holder === undefined ? undefined : holderClause(holder, launcher);
|
|
92
|
+
if (known !== undefined)
|
|
93
|
+
return why + known + overrideTail(launcher);
|
|
80
94
|
if (launcher === "debugger") {
|
|
81
95
|
return (why +
|
|
82
96
|
`Deal with whatever is already holding it — which remedy applies depends on what it is: ` +
|
|
@@ -99,4 +113,106 @@ export function portConflictMessage(host, port, launcher = "run") {
|
|
|
99
113
|
`tool against it. To drive more than one game at once, use runtime_spawn_peers, which allocates ` +
|
|
100
114
|
`a distinct port per peer.`);
|
|
101
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* The sentence that replaces the conditional remedy list once `port-holder.ts` has named the
|
|
118
|
+
* holder — or `undefined` when it could not, so the caller keeps the list.
|
|
119
|
+
*
|
|
120
|
+
* 🔴 ONLY A LEDGER MATCH NAMES A STOP TOOL. `godot_stop` is offered when the pid is one
|
|
121
|
+
* `godot_run_managed` started and `runtime_peer_stop` when it is a peer; a Godot this server
|
|
122
|
+
* did not start still gets the conditions that apply to it, narrowed to it, because whether
|
|
123
|
+
* it is under the debugger is not something a pid says.
|
|
124
|
+
*/
|
|
125
|
+
function holderClause(holder, launcher) {
|
|
126
|
+
const move = `point this server at a free port with BREAKPOINT_RUNTIME_PORT`;
|
|
127
|
+
if (holder.kind === "unavailable")
|
|
128
|
+
return undefined;
|
|
129
|
+
if (holder.kind === "none_visible") {
|
|
130
|
+
return (`No process this account can see is listening on it, so it belongs to another user or to the system, ` +
|
|
131
|
+
`or it exited a moment ago — no tool here can stop it. Retry once, and if it is refused again, ${move}. `);
|
|
132
|
+
}
|
|
133
|
+
const hs = holder.holders;
|
|
134
|
+
if (hs.length !== 1) {
|
|
135
|
+
return `It is held by ${hs.length} processes — ${holdersPhrase(hs)}. Stop or quit each of them, or ${move}. `;
|
|
136
|
+
}
|
|
137
|
+
const h = hs[0];
|
|
138
|
+
const held = `It is held by ${holderPhrase(h)}`;
|
|
139
|
+
const stop = certainStop(h);
|
|
140
|
+
if (stop)
|
|
141
|
+
return `${held}: ${stop}, or ${move}. `;
|
|
142
|
+
switch (h.owner.kind) {
|
|
143
|
+
case "godot_run_project":
|
|
144
|
+
return `${held}. No tool can stop a detached game, so quit it in its game window, or ${move}. `;
|
|
145
|
+
case "this_server":
|
|
146
|
+
return `${held}; no tool here can release it, so ${move}. `;
|
|
147
|
+
case "godot":
|
|
148
|
+
return launcher === "debugger"
|
|
149
|
+
? `${held}: if it is already under the debugger, dbg_attach / cs_dbg_attach reaches it instead of ` +
|
|
150
|
+
`launching a second game; otherwise quit it in its window, or ${move}. `
|
|
151
|
+
: `${held}: quit it in its window, or end the debug session that launched it, or ${move}. `;
|
|
152
|
+
default:
|
|
153
|
+
return `${held}, which no Breakpoint tool can stop: quit it, or ${move}. `;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/** The override and the peers pointer — true whoever holds the port, so kept in every variant. */
|
|
157
|
+
function overrideTail(launcher) {
|
|
158
|
+
const peers = `To drive more than one game at once, use runtime_spawn_peers, which allocates a distinct port per peer.`;
|
|
159
|
+
if (launcher === "debugger") {
|
|
160
|
+
return (`Pass allow_port_conflict:true to launch anyway: breakpoints, stepping and variable inspection will all ` +
|
|
161
|
+
`work normally, because a DAP session is addressed by session rather than by port — but every runtime_* ` +
|
|
162
|
+
`call would go to the process holding the port, not to the game you just launched. ` + peers);
|
|
163
|
+
}
|
|
164
|
+
return (`Pass allow_port_conflict:true to start it anyway — reasonable only if you want the process for its ` +
|
|
165
|
+
`console output or its side effects and will not use any runtime_* tool against it. ` + peers);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* 🆕 318 — `breakpoint_ports`: every port this server dials, and who is on it.
|
|
169
|
+
*
|
|
170
|
+
* 🔴 TWO READERS, AND WHICH ONE DECIDED A ROW IS SAID. The listener table (`port-holder.ts`) is
|
|
171
|
+
* the one that can name a holder; the bind probe (`portFree`) is the one that can tell "nobody
|
|
172
|
+
* this account can see" apart from "nobody at all", which lsof prints identically. And the
|
|
173
|
+
* bind probe has a blind spot the table does not, measured on macOS at 318: a node listener on
|
|
174
|
+
* `*:<port>` or `[::1]:<port>` left `127.0.0.1:<port>` bindable. So a row is `held` whenever the
|
|
175
|
+
* table lists a listener, and `free` only when the table lists nothing AND the bind succeeds —
|
|
176
|
+
* or, where the table could not be read, when the bind succeeds and the note says that is all
|
|
177
|
+
* that was asked.
|
|
178
|
+
*
|
|
179
|
+
* Only this machine's loopback is looked at. A host that names another machine is `unknown`,
|
|
180
|
+
* because binding a remote address locally answers nothing about that machine.
|
|
181
|
+
*/
|
|
182
|
+
export async function readPorts(cfg) {
|
|
183
|
+
const roster = [
|
|
184
|
+
{ name: "editor-bridge", host: cfg.bridgeHost, port: cfg.bridgePort },
|
|
185
|
+
{ name: "runtime-bridge", host: cfg.runtimeHost, port: cfg.runtimePort },
|
|
186
|
+
{ name: "gdscript-lsp", host: cfg.lspHost, port: cfg.lspPort },
|
|
187
|
+
{ name: "gdscript-dap", host: cfg.dapHost, port: cfg.dapPort },
|
|
188
|
+
...ownedPeers().map((p) => ({ name: `peer:${p.id}`, host: cfg.runtimeHost, port: p.port })),
|
|
189
|
+
];
|
|
190
|
+
return Promise.all(roster.map((r) => readPortRow(r, cfg.godotBin)));
|
|
191
|
+
}
|
|
192
|
+
async function readPortRow(r, godotBin) {
|
|
193
|
+
const base = { name: r.name, host: r.host, port: r.port };
|
|
194
|
+
if (!isLoopbackHost(r.host)) {
|
|
195
|
+
return { ...base, state: "unknown", holders: [], note: `${r.host} is not this machine's loopback, so nothing here can read its listeners` };
|
|
196
|
+
}
|
|
197
|
+
const holder = await whoHolds(r.host, r.port, godotBin);
|
|
198
|
+
if (holder.kind === "found") {
|
|
199
|
+
const holders = holder.holders.map((h) => ({
|
|
200
|
+
pid: h.pid,
|
|
201
|
+
command: h.command,
|
|
202
|
+
addresses: h.addresses,
|
|
203
|
+
owner: h.owner.kind,
|
|
204
|
+
id: "id" in h.owner ? h.owner.id : null,
|
|
205
|
+
}));
|
|
206
|
+
return { ...base, state: "held", holders, note: null };
|
|
207
|
+
}
|
|
208
|
+
const bindable = await portFree(r.host, r.port);
|
|
209
|
+
if (holder.kind === "none_visible") {
|
|
210
|
+
return bindable
|
|
211
|
+
? { ...base, state: "free", holders: [], note: null }
|
|
212
|
+
: { ...base, state: "held", holders: [], note: "held by a process this account cannot see (another user's, or the system's)" };
|
|
213
|
+
}
|
|
214
|
+
return bindable
|
|
215
|
+
? { ...base, state: "free", holders: [], note: `${holder.reason}; free means only that ${r.host}:${r.port} could be bound` }
|
|
216
|
+
: { ...base, state: "held", holders: [], note: `the holder could not be named: ${holder.reason}` };
|
|
217
|
+
}
|
|
102
218
|
//# sourceMappingURL=ports.js.map
|
package/dist/ports.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ports.js","sourceRoot":"","sources":["../src/ports.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"ports.js","sourceRoot":"","sources":["../src/ports.ts"],"names":[],"mappings":"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"}
|
package/dist/recipes.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* it's **free** (MIT, shipped in the server), and it sits **over typed,
|
|
8
8
|
* schema-validated, undoable tools** — so the contract is executed by the
|
|
9
9
|
* server, not merely described in prose the model might misapply. Recipes are
|
|
10
|
-
* discoverable via MCP `prompts/list`; they add **no tools** (the
|
|
10
|
+
* discoverable via MCP `prompts/list`; they add **no tools** (the 293-tool
|
|
11
11
|
* count is unchanged) and cost nothing until a client pulls one.
|
|
12
12
|
*/
|
|
13
13
|
import { z } from "zod";
|
package/dist/schemas.js
CHANGED
|
@@ -211,6 +211,24 @@ export const outputSchemas = {
|
|
|
211
211
|
hint: z.string().optional(),
|
|
212
212
|
})),
|
|
213
213
|
},
|
|
214
|
+
// 🆕 318 — `breakpoint_ports`. `holders` is empty, never absent, on a free row: "nobody" is
|
|
215
|
+
// the answer a caller asked for, and an absent field would make it guess between that and "not asked".
|
|
216
|
+
breakpoint_ports: {
|
|
217
|
+
ports: z.array(z.object({
|
|
218
|
+
name: z.string(),
|
|
219
|
+
host: z.string(),
|
|
220
|
+
port: z.number(),
|
|
221
|
+
state: z.string(),
|
|
222
|
+
holders: z.array(z.object({
|
|
223
|
+
pid: z.number(),
|
|
224
|
+
command: z.string(),
|
|
225
|
+
addresses: z.array(z.string()),
|
|
226
|
+
owner: z.string(),
|
|
227
|
+
id: z.string().nullable(),
|
|
228
|
+
})),
|
|
229
|
+
note: z.string().nullable(),
|
|
230
|
+
})),
|
|
231
|
+
},
|
|
214
232
|
godot_version: { version: z.string(), raw: capturedRaw },
|
|
215
233
|
godot_launch_editor: { launched: z.boolean(), pid: z.number().nullable(), project: z.string() },
|
|
216
234
|
// 🔴 `running` ALONE WAS THE DEFECT (249, closed 257). It reported that spawn()
|