wicked-brain 0.7.2 → 0.8.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/package.json
CHANGED
|
@@ -16,28 +16,52 @@ function getArg(name) {
|
|
|
16
16
|
return idx !== -1 && args[idx + 1] ? args[idx + 1] : null;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
// --version / -v: print root package.json version and exit.
|
|
20
|
+
// Resolves relative to this file so the published install reads its own manifest.
|
|
21
|
+
if (args.includes("--version") || args.includes("-v")) {
|
|
22
|
+
const pkgUrl = new URL("../../package.json", import.meta.url);
|
|
23
|
+
const pkg = JSON.parse(readFileSync(pkgUrl, "utf-8"));
|
|
24
|
+
console.log(pkg.version);
|
|
25
|
+
exit(0);
|
|
26
|
+
}
|
|
27
|
+
|
|
19
28
|
const brainPath = resolve(getArg("brain") || ".");
|
|
20
29
|
const preferredPort = parseInt(getArg("port") || "4242", 10);
|
|
30
|
+
// Explicit --port means "bind this exact port or fail" — no probe.
|
|
31
|
+
const portExplicit = args.includes("--port");
|
|
21
32
|
const configPath = join(brainPath, "brain.json");
|
|
22
33
|
// Source path for LSP workspace root — prefer --source flag, fall back to config, then brainPath
|
|
23
34
|
const sourceArgRaw = getArg("source");
|
|
24
35
|
const sourceArg = sourceArgRaw ? resolve(sourceArgRaw) : null;
|
|
25
36
|
|
|
26
|
-
/**
|
|
27
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Listen on `startPort`, probing upward on EADDRINUSE. Probes using the real
|
|
39
|
+
* server instance so the bind semantics (dual-stack IPv4+IPv6) match the
|
|
40
|
+
* eventual listener — a separate 127.0.0.1 probe would miss an IPv6-only
|
|
41
|
+
* conflict and produce a false "free" result.
|
|
42
|
+
*/
|
|
43
|
+
function listenWithProbe(server, startPort, maxProbe) {
|
|
28
44
|
return new Promise((resolve, reject) => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
45
|
+
let p = startPort;
|
|
46
|
+
const attempt = () => {
|
|
47
|
+
const onError = (err) => {
|
|
48
|
+
server.off("listening", onListen);
|
|
49
|
+
if (err.code === "EADDRINUSE" && p < startPort + maxProbe - 1) {
|
|
50
|
+
p += 1;
|
|
51
|
+
attempt();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
reject(err);
|
|
55
|
+
};
|
|
56
|
+
const onListen = () => {
|
|
57
|
+
server.off("error", onError);
|
|
58
|
+
resolve(p);
|
|
59
|
+
};
|
|
60
|
+
server.once("error", onError);
|
|
61
|
+
server.once("listening", onListen);
|
|
62
|
+
server.listen(p);
|
|
39
63
|
};
|
|
40
|
-
|
|
64
|
+
attempt();
|
|
41
65
|
});
|
|
42
66
|
}
|
|
43
67
|
|
|
@@ -230,9 +254,13 @@ watcher.onFileChange((relPath, absPath, content, eventType) => {
|
|
|
230
254
|
lsp.handleFileChange(relPath, absPath, content, eventType);
|
|
231
255
|
});
|
|
232
256
|
|
|
233
|
-
|
|
257
|
+
// Bind the real server. Probe upward on EADDRINUSE unless the user passed
|
|
258
|
+
// --port explicitly (in which case bind that port or fail loudly).
|
|
259
|
+
const port = await listenWithProbe(server, preferredPort, portExplicit ? 1 : 20);
|
|
234
260
|
|
|
235
|
-
// Write actual port back to config so skills can always find the server
|
|
261
|
+
// Write actual bound port back to config so skills can always find the server.
|
|
262
|
+
// Must happen AFTER listen succeeds — a pre-listen write would leave a stale
|
|
263
|
+
// value if the bind failed.
|
|
236
264
|
try {
|
|
237
265
|
let metaConfig = {};
|
|
238
266
|
try { metaConfig = JSON.parse(readFileSync(metaConfigPath, "utf-8")); } catch {}
|
|
@@ -242,18 +270,16 @@ try {
|
|
|
242
270
|
console.error(`Warning: could not write port to config: ${err.message}`);
|
|
243
271
|
}
|
|
244
272
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
brain_id: brainId, port, pid,
|
|
251
|
-
});
|
|
252
|
-
if (busReady) {
|
|
253
|
-
try {
|
|
254
|
-
memorySubscriber = await startMemorySubscriber({ brainPath, brainId, db });
|
|
255
|
-
} catch (err) {
|
|
256
|
-
console.error(`[memory-subscriber] failed to start: ${err.message}`);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
273
|
+
console.log(`wicked-brain-server running on port ${port} (brain: ${brainId}, pid: ${pid})`);
|
|
274
|
+
watcher.start();
|
|
275
|
+
const busReady = await waitForBus();
|
|
276
|
+
emitEvent("wicked.server.started", "brain.system", {
|
|
277
|
+
brain_id: brainId, port, pid,
|
|
259
278
|
});
|
|
279
|
+
if (busReady) {
|
|
280
|
+
try {
|
|
281
|
+
memorySubscriber = await startMemorySubscriber({ brainPath, brainId, db });
|
|
282
|
+
} catch (err) {
|
|
283
|
+
console.error(`[memory-subscriber] failed to start: ${err.message}`);
|
|
284
|
+
}
|
|
285
|
+
}
|
package/server/package.json
CHANGED
|
@@ -60,9 +60,12 @@ If the result is `not installed`, the package was never globally installed (the
|
|
|
60
60
|
user may have been running via `npx` only). Treat this as "needs install" and
|
|
61
61
|
proceed to Step 4.
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
`wicked-brain-server --version` (v0.8.0+) prints the installed version directly.
|
|
64
|
+
It's safe to call the binary by its installed path — e.g.
|
|
65
|
+
`$(npm config get prefix)/bin/wicked-brain-server --version`. **Avoid
|
|
66
|
+
`npx wicked-brain-server --version`** — npx may resolve to a cached copy that
|
|
67
|
+
isn't the globally installed one that actually runs when brain servers start,
|
|
68
|
+
so the number it reports can lie about what will serve requests.
|
|
66
69
|
|
|
67
70
|
### Step 2: Check latest version on npm
|
|
68
71
|
|