shadok-ai 0.8.27 → 0.8.28
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.
|
@@ -6,7 +6,22 @@ import fs from "node:fs";
|
|
|
6
6
|
import os from "node:os";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
|
-
|
|
9
|
+
// The WebSocket implementation, chosen at load: Node's BUILT-IN global first,
|
|
10
|
+
// the `ws` package only as a fallback.
|
|
11
|
+
//
|
|
12
|
+
// Why the built-in first: seeded into ~/.claude/skills so any agent can pilot,
|
|
13
|
+
// this file has no node_modules to resolve `ws` from, and the bare import broke
|
|
14
|
+
// every agent piloting outside the repo with ERR_MODULE_NOT_FOUND.
|
|
15
|
+
//
|
|
16
|
+
// Why `ws` is still needed: the global WebSocket is only unflagged from Node 22.
|
|
17
|
+
// This project supports Node >= 20 (README, and ci.yml runs the suite on 20),
|
|
18
|
+
// where `globalThis.WebSocket` is undefined — dropping the package outright
|
|
19
|
+
// traded a failure that hit agents outside the repo for one that hits EVERY
|
|
20
|
+
// Node 20 user, in-repo included. The `.catch` keeps the absent-package case
|
|
21
|
+
// (seeded copy) from throwing at import time, so the pure helpers this module
|
|
22
|
+
// exports stay usable; `makeWS` reports it instead, when someone actually
|
|
23
|
+
// connects.
|
|
24
|
+
const WS = globalThis.WebSocket ?? (await import("ws").catch(() => null))?.default;
|
|
10
25
|
|
|
11
26
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
27
|
// Only used to auto-start a server when none is reachable (a dev running pilotctl
|
|
@@ -24,6 +39,31 @@ export const wsUrl = () => `ws://localhost:${port()}/ws`;
|
|
|
24
39
|
export const authHeaders = () => (process.env.SHADOK_AUTH ? { cookie: process.env.SHADOK_AUTH } : {});
|
|
25
40
|
export const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
26
41
|
|
|
42
|
+
// The built-in WebSocket is WHATWG (addEventListener + event.data); the rest of
|
|
43
|
+
// this file uses the `ws` package's EventEmitter surface. Bridge them: `.on` /
|
|
44
|
+
// `.once`, handing a `message` listener the raw payload (event.data — a string
|
|
45
|
+
// for the JSON frames the server sends). Only these two methods are used here.
|
|
46
|
+
// `ws` already has them, so it is returned untouched.
|
|
47
|
+
//
|
|
48
|
+
// Both accept the non-standard `{ headers }` option, which is what carries the
|
|
49
|
+
// SHADOK_AUTH cookie past the password gate — verified against a real upgrade
|
|
50
|
+
// handler on the built-in, not assumed.
|
|
51
|
+
function makeWS(url, opts) {
|
|
52
|
+
if (!WS)
|
|
53
|
+
throw new Error(
|
|
54
|
+
"no WebSocket available: Node < 22 has no global one, and the `ws` package " +
|
|
55
|
+
"is not resolvable from here (a globally-seeded skill has no node_modules). " +
|
|
56
|
+
"Run pilotctl from the repo, or upgrade to Node 22+.",
|
|
57
|
+
);
|
|
58
|
+
const ws = new WS(url, opts);
|
|
59
|
+
if (typeof ws.on === "function") return ws; // the `ws` package: already an emitter
|
|
60
|
+
const add = (type, fn, once) =>
|
|
61
|
+
ws.addEventListener(type, type === "message" ? (e) => fn(e.data) : fn, once ? { once: true } : undefined);
|
|
62
|
+
ws.on = (type, fn) => (add(type, fn, false), ws);
|
|
63
|
+
ws.once = (type, fn) => (add(type, fn, true), ws);
|
|
64
|
+
return ws;
|
|
65
|
+
}
|
|
66
|
+
|
|
27
67
|
export function stateDir() {
|
|
28
68
|
return process.env.SHADOK_STATE_DIR ?? path.join(os.homedir(), ".shadok-ai", "pilotctl");
|
|
29
69
|
}
|
|
@@ -69,7 +109,7 @@ export function parseArgs(argv) {
|
|
|
69
109
|
|
|
70
110
|
function connect() {
|
|
71
111
|
return new Promise((resolve, reject) => {
|
|
72
|
-
const ws =
|
|
112
|
+
const ws = makeWS(wsUrl(), { headers: authHeaders() });
|
|
73
113
|
ws.once("open", () => resolve(ws));
|
|
74
114
|
ws.once("error", reject);
|
|
75
115
|
});
|