token-goat 2.9.28 → 2.9.29
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 +2 -0
- package/dist/{token-goat-chunk-OZRSREKR.mjs → token-goat-chunk-2AWQ2R5X.mjs} +2 -2
- package/dist/{token-goat-chunk-5NNYIUGV.mjs → token-goat-chunk-2NNUA2LR.mjs} +4 -4
- package/dist/{token-goat-chunk-4RN64ZND.mjs → token-goat-chunk-2WOUYWLM.mjs} +2 -1
- package/dist/{token-goat-chunk-HUDC5GS5.mjs → token-goat-chunk-435UQTKD.mjs} +5 -3
- package/dist/{token-goat-chunk-6DQNNFJ6.mjs → token-goat-chunk-44BM7DDQ.mjs} +3 -3
- package/dist/{token-goat-chunk-4JMWPWCS.mjs → token-goat-chunk-52NSDWYY.mjs} +2 -2
- package/dist/{token-goat-chunk-IHKZ3QNA.mjs → token-goat-chunk-67BNIKKO.mjs} +19 -16
- package/dist/{token-goat-chunk-XBESNWEX.mjs → token-goat-chunk-6AK46ZT7.mjs} +2 -3
- package/dist/{token-goat-chunk-M56BWPBN.mjs → token-goat-chunk-7CPMDFGB.mjs} +166 -40
- package/dist/token-goat-chunk-ASLWOQ3I.mjs +14 -0
- package/dist/{token-goat-chunk-QM76S6YS.mjs → token-goat-chunk-BGYOZ6DO.mjs} +6 -4
- package/dist/{token-goat-chunk-JXK2HQXS.mjs → token-goat-chunk-C5YPNZKQ.mjs} +3 -3
- package/dist/{token-goat-chunk-MVSWBNMD.mjs → token-goat-chunk-CIQ2FTY3.mjs} +19 -14
- package/dist/{token-goat-chunk-BJBRGPBX.mjs → token-goat-chunk-D4ETHJD6.mjs} +6 -4
- package/dist/{token-goat-chunk-VE27HPIF.mjs → token-goat-chunk-DNRPXHYH.mjs} +21 -17
- package/dist/{token-goat-chunk-YWSP6IU7.mjs → token-goat-chunk-DNSPXQXQ.mjs} +2 -2
- package/dist/token-goat-chunk-DPNLUJWB.mjs +220 -0
- package/dist/{token-goat-chunk-I7CB3X4K.mjs → token-goat-chunk-E4ZOJIZK.mjs} +10 -7
- package/dist/{token-goat-chunk-IZXKVT4A.mjs → token-goat-chunk-E5TK5DNO.mjs} +11 -4
- package/dist/{token-goat-chunk-MMLMALWK.mjs → token-goat-chunk-EUSDXRXU.mjs} +60 -12
- package/dist/{token-goat-chunk-7R2XYKC5.mjs → token-goat-chunk-FTP4U4QA.mjs} +12 -9
- package/dist/{token-goat-chunk-LEG3JNJ6.mjs → token-goat-chunk-G23DWHV4.mjs} +17 -14
- package/dist/{token-goat-chunk-L7SDVGBT.mjs → token-goat-chunk-G7IWXCFF.mjs} +49 -23
- package/dist/{token-goat-chunk-NILVK7XM.mjs → token-goat-chunk-GLXRTTLE.mjs} +7 -5
- package/dist/{token-goat-chunk-6CCQDAYY.mjs → token-goat-chunk-H5J3C56Q.mjs} +35 -16
- package/dist/{token-goat-chunk-Q4S3UQGO.mjs → token-goat-chunk-HNFZZHFW.mjs} +2 -2
- package/dist/{token-goat-chunk-CBMY2FGI.mjs → token-goat-chunk-HUYUHODZ.mjs} +572 -230
- package/dist/token-goat-chunk-IVE6U7KV.mjs +53 -0
- package/dist/{token-goat-chunk-F7QZRIWM.mjs → token-goat-chunk-IVWI2OCK.mjs} +8 -30
- package/dist/{token-goat-chunk-GMOUBOX4.mjs → token-goat-chunk-JTKCQMQA.mjs} +37 -5
- package/dist/{token-goat-chunk-6SGLIPQB.mjs → token-goat-chunk-KOPIR3KZ.mjs} +12 -9
- package/dist/token-goat-chunk-L7H3U27L.mjs +35 -0
- package/dist/{token-goat-chunk-FSTWAOW6.mjs → token-goat-chunk-LZNBQTDK.mjs} +6 -4
- package/dist/token-goat-chunk-MELOKFDJ.mjs +199 -0
- package/dist/{token-goat-chunk-VWZKZPSR.mjs → token-goat-chunk-NMBWLRHW.mjs} +76 -39
- package/dist/{token-goat-chunk-HXNAC4ZF.mjs → token-goat-chunk-O6I2XU4P.mjs} +12 -10
- package/dist/{token-goat-chunk-MAMQPC43.mjs → token-goat-chunk-ONXH6NZ5.mjs} +1 -1
- package/dist/token-goat-chunk-ORNFMIER.mjs +295 -0
- package/dist/{token-goat-chunk-66LODAUT.mjs → token-goat-chunk-PGTH2U4C.mjs} +1 -1
- package/dist/{token-goat-chunk-SJEKA7Y2.mjs → token-goat-chunk-PKRWMHVP.mjs} +76 -64
- package/dist/{token-goat-chunk-DA43OE7L.mjs → token-goat-chunk-PQ53BSCF.mjs} +1 -1
- package/dist/{token-goat-chunk-RSS3TLXU.mjs → token-goat-chunk-PYSUADX4.mjs} +2 -2
- package/dist/{token-goat-chunk-EL7M26WP.mjs → token-goat-chunk-QO3LXVVR.mjs} +185 -104
- package/dist/{token-goat-chunk-XI2VFAV6.mjs → token-goat-chunk-RLP6J7WR.mjs} +6 -6
- package/dist/token-goat-chunk-RQGGMPCR.mjs +205 -0
- package/dist/{token-goat-chunk-6Z5ULNE5.mjs → token-goat-chunk-RTMVLHWX.mjs} +165 -60
- package/dist/{token-goat-chunk-E3K3BTEQ.mjs → token-goat-chunk-S4VSXURL.mjs} +8 -6
- package/dist/{token-goat-chunk-LKSXAMJB.mjs → token-goat-chunk-SE6E4BKJ.mjs} +1 -1
- package/dist/token-goat-chunk-TCQANXYC.mjs +351 -0
- package/dist/{token-goat-chunk-GGLEE35R.mjs → token-goat-chunk-TDUT2CL6.mjs} +7 -7
- package/dist/{token-goat-chunk-CC2PYJM7.mjs → token-goat-chunk-TGOXNAHW.mjs} +54 -112
- package/dist/{token-goat-chunk-XKY4VKJ4.mjs → token-goat-chunk-UA5BKWWQ.mjs} +1 -1
- package/dist/{token-goat-chunk-UBUKHVYW.mjs → token-goat-chunk-UXSXQQIY.mjs} +1 -1
- package/dist/{token-goat-chunk-D5ICEPSB.mjs → token-goat-chunk-VMFWNHGR.mjs} +79 -68
- package/dist/token-goat-chunk-VQ6F6T7X.mjs +36 -0
- package/dist/{token-goat-chunk-4STDIGYC.mjs → token-goat-chunk-VZQEWRVH.mjs} +6 -4
- package/dist/{token-goat-chunk-OSUFN2FV.mjs → token-goat-chunk-XB5KKOCG.mjs} +5 -25
- package/dist/{token-goat-chunk-L45ZQRT7.mjs → token-goat-chunk-XYWPOSCN.mjs} +57 -615
- package/dist/{token-goat-chunk-4JJBFT7V.mjs → token-goat-chunk-YAGLESS3.mjs} +8 -5
- package/dist/token-goat-chunk-YKSRAWUU.mjs +33 -0
- package/dist/{token-goat-chunk-F2ARFHLJ.mjs → token-goat-chunk-YOOVFPTP.mjs} +2 -2
- package/dist/{token-goat-chunk-EEIDFMEM.mjs → token-goat-chunk-YZAAZU2S.mjs} +12 -3
- package/dist/token-goat-chunk-Z6KBMOBI.mjs +53 -0
- package/dist/{token-goat-chunk-RJH64KQH.mjs → token-goat-chunk-ZER6EAXZ.mjs} +3 -3
- package/dist/token-goat-hook-client.cjs +475 -0
- package/dist/token-goat-hook-client.mjs +26 -0
- package/dist/token-goat-hook.mjs +31 -27
- package/dist/token-goat.core.mjs +9 -44
- package/docs/C4_RUNTIME_ARCHITECTURE.md +2 -2
- package/docs/cli.md +3 -2
- package/docs/install.md +16 -14
- package/package.json +1 -1
- package/dist/token-goat-chunk-7MAFDRVR.mjs +0 -47
- package/dist/token-goat-chunk-BCN2YQC6.mjs +0 -32
- package/dist/token-goat-chunk-D7GHQKQD.mjs +0 -30
- package/dist/token-goat-chunk-IFORDBGC.mjs +0 -192
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { createRequire as __cjsRequire } from 'node:module';
|
|
2
|
+
const require = __cjsRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
serveOne,
|
|
5
|
+
swapEnv
|
|
6
|
+
} from "./token-goat-chunk-S4VSXURL.mjs";
|
|
7
|
+
import {
|
|
8
|
+
relayInProcess
|
|
9
|
+
} from "./token-goat-chunk-QO3LXVVR.mjs";
|
|
10
|
+
import "./token-goat-chunk-IVWI2OCK.mjs";
|
|
11
|
+
import "./token-goat-chunk-DNRPXHYH.mjs";
|
|
12
|
+
import "./token-goat-chunk-RTMVLHWX.mjs";
|
|
13
|
+
import "./token-goat-chunk-L7H3U27L.mjs";
|
|
14
|
+
import "./token-goat-chunk-RRNZMM3A.mjs";
|
|
15
|
+
import "./token-goat-chunk-E4ZOJIZK.mjs";
|
|
16
|
+
import "./token-goat-chunk-E5TK5DNO.mjs";
|
|
17
|
+
import "./token-goat-chunk-ZER6EAXZ.mjs";
|
|
18
|
+
import "./token-goat-chunk-44BM7DDQ.mjs";
|
|
19
|
+
import "./token-goat-chunk-EUSDXRXU.mjs";
|
|
20
|
+
import "./token-goat-chunk-G7IWXCFF.mjs";
|
|
21
|
+
import "./token-goat-chunk-H5J3C56Q.mjs";
|
|
22
|
+
import "./token-goat-chunk-TDUT2CL6.mjs";
|
|
23
|
+
import "./token-goat-chunk-ONXH6NZ5.mjs";
|
|
24
|
+
import "./token-goat-chunk-O6I2XU4P.mjs";
|
|
25
|
+
import "./token-goat-chunk-D4ETHJD6.mjs";
|
|
26
|
+
import "./token-goat-chunk-52NSDWYY.mjs";
|
|
27
|
+
import "./token-goat-chunk-2WOUYWLM.mjs";
|
|
28
|
+
import "./token-goat-chunk-CIQ2FTY3.mjs";
|
|
29
|
+
import {
|
|
30
|
+
PROTOCOL_VERSION,
|
|
31
|
+
SERVER_SLOTS,
|
|
32
|
+
bundleEntryFiles,
|
|
33
|
+
configStamp,
|
|
34
|
+
endpointFor,
|
|
35
|
+
ensureServerKey,
|
|
36
|
+
mac,
|
|
37
|
+
macMatches,
|
|
38
|
+
nonce,
|
|
39
|
+
readFrames,
|
|
40
|
+
removeMarker,
|
|
41
|
+
serverKeyPath,
|
|
42
|
+
touchMarker,
|
|
43
|
+
writeFrame
|
|
44
|
+
} from "./token-goat-chunk-DPNLUJWB.mjs";
|
|
45
|
+
import "./token-goat-chunk-3BTK54F3.mjs";
|
|
46
|
+
import "./token-goat-chunk-VMFWNHGR.mjs";
|
|
47
|
+
import "./token-goat-chunk-435UQTKD.mjs";
|
|
48
|
+
import "./token-goat-chunk-7CPMDFGB.mjs";
|
|
49
|
+
import {
|
|
50
|
+
hookServerEnabled
|
|
51
|
+
} from "./token-goat-chunk-TGOXNAHW.mjs";
|
|
52
|
+
import "./token-goat-chunk-XB5KKOCG.mjs";
|
|
53
|
+
import {
|
|
54
|
+
clearPerRequestCaches
|
|
55
|
+
} from "./token-goat-chunk-YZAAZU2S.mjs";
|
|
56
|
+
import "./token-goat-chunk-IVE6U7KV.mjs";
|
|
57
|
+
import "./token-goat-chunk-XYWPOSCN.mjs";
|
|
58
|
+
import "./token-goat-chunk-TCQANXYC.mjs";
|
|
59
|
+
import "./token-goat-chunk-NMTKNYGF.mjs";
|
|
60
|
+
import {
|
|
61
|
+
VERSION,
|
|
62
|
+
configPath,
|
|
63
|
+
ensureDataDirPrivate
|
|
64
|
+
} from "./token-goat-chunk-MELOKFDJ.mjs";
|
|
65
|
+
import "./token-goat-chunk-Y4AFKTHK.mjs";
|
|
66
|
+
import "./token-goat-chunk-JTKCQMQA.mjs";
|
|
67
|
+
import {
|
|
68
|
+
init_define_import_meta_env
|
|
69
|
+
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
70
|
+
|
|
71
|
+
// src/hook_server.ts
|
|
72
|
+
init_define_import_meta_env();
|
|
73
|
+
import * as fs from "node:fs";
|
|
74
|
+
import * as net from "node:net";
|
|
75
|
+
import * as os from "node:os";
|
|
76
|
+
var IDLE_EXIT_MS = { primary: 30 * 6e4, overflow: 3 * 6e4 };
|
|
77
|
+
var KEY_CHECK_MS = 2e3;
|
|
78
|
+
var HANDSHAKE_IDLE_MS = 1e4;
|
|
79
|
+
function bundleStamp() {
|
|
80
|
+
return bundleEntryFiles().map((f) => {
|
|
81
|
+
try {
|
|
82
|
+
const st = fs.statSync(f);
|
|
83
|
+
return `${st.size}:${st.mtimeMs}`;
|
|
84
|
+
} catch {
|
|
85
|
+
return "-";
|
|
86
|
+
}
|
|
87
|
+
}).join("|");
|
|
88
|
+
}
|
|
89
|
+
var enabledMemo;
|
|
90
|
+
function stillEnabled() {
|
|
91
|
+
const key = `${process.env["TOKEN_GOAT_HOOK_SERVER"] ?? ""}|${configPath()}|${configStamp()}`;
|
|
92
|
+
if (enabledMemo?.key !== key) enabledMemo = { key, enabled: hookServerEnabled() };
|
|
93
|
+
return enabledMemo.enabled;
|
|
94
|
+
}
|
|
95
|
+
function retirementReason(loadedStamp) {
|
|
96
|
+
if (bundleStamp() !== loadedStamp) return "bundle replaced";
|
|
97
|
+
if (!stillEnabled()) return "disabled";
|
|
98
|
+
return void 0;
|
|
99
|
+
}
|
|
100
|
+
async function handle(request, runCli, send) {
|
|
101
|
+
clearPerRequestCaches();
|
|
102
|
+
if (request.kind === "cli") {
|
|
103
|
+
const res = await serveOne({ id: 0, argv: request.argv, cwd: request.cwd, env: request.env }, runCli, clearPerRequestCaches);
|
|
104
|
+
return send({ ok: true, stdout: res.stdout, stderr: res.stderr, status: res.status });
|
|
105
|
+
}
|
|
106
|
+
const startedAt = performance.now();
|
|
107
|
+
const cwdBefore = process.cwd();
|
|
108
|
+
const restoreEnv = swapEnv(request.env);
|
|
109
|
+
const afterReply = [];
|
|
110
|
+
try {
|
|
111
|
+
process.chdir(request.cwd);
|
|
112
|
+
const payload = JSON.parse(request.input);
|
|
113
|
+
const stdout = await relayInProcess(request.event, payload, request.harnessWaitMs, { elapsedMs: () => request.elapsedMs + (performance.now() - startedAt), afterReply: (work) => afterReply.push(work) });
|
|
114
|
+
send({ ok: true, stdout });
|
|
115
|
+
for (const work of afterReply) work();
|
|
116
|
+
} finally {
|
|
117
|
+
restoreEnv();
|
|
118
|
+
try {
|
|
119
|
+
process.chdir(cwdBefore);
|
|
120
|
+
} catch {
|
|
121
|
+
}
|
|
122
|
+
clearPerRequestCaches();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function listen(server, endpoint) {
|
|
126
|
+
const tryListen = () => new Promise((resolve) => {
|
|
127
|
+
server.once("error", resolve);
|
|
128
|
+
server.listen({ path: endpoint, readableAll: false, writableAll: false }, () => {
|
|
129
|
+
server.removeListener("error", resolve);
|
|
130
|
+
resolve(void 0);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
return tryListen().then(async (err) => {
|
|
134
|
+
if (err === void 0) return true;
|
|
135
|
+
if (err.code !== "EADDRINUSE" || process.platform === "win32") return false;
|
|
136
|
+
const alive = await new Promise((resolve) => {
|
|
137
|
+
const probe = net.connect(endpoint);
|
|
138
|
+
probe.once("connect", () => {
|
|
139
|
+
probe.destroy();
|
|
140
|
+
resolve(true);
|
|
141
|
+
});
|
|
142
|
+
probe.once("error", () => resolve(false));
|
|
143
|
+
});
|
|
144
|
+
if (alive) return false;
|
|
145
|
+
fs.rmSync(endpoint, { force: true });
|
|
146
|
+
return await tryListen() === void 0;
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
async function runHookServer(slot, runCli) {
|
|
150
|
+
if (!Number.isInteger(slot) || slot < 0 || slot >= SERVER_SLOTS) throw new Error(`--slot must be an integer from 0 to ${SERVER_SLOTS - 1}`);
|
|
151
|
+
if (!hookServerEnabled()) {
|
|
152
|
+
touchMarker("disabled", configStamp());
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
ensureDataDirPrivate();
|
|
156
|
+
const key = ensureServerKey();
|
|
157
|
+
const keyPath = serverKeyPath();
|
|
158
|
+
const loadedStamp = bundleStamp();
|
|
159
|
+
const endpoint = endpointFor(slot);
|
|
160
|
+
process.chdir(os.tmpdir());
|
|
161
|
+
const status = { pid: process.pid, slot, version: VERSION, startedAt: Date.now(), lastUsedAt: Date.now(), served: 0, errors: 0 };
|
|
162
|
+
let busy = false;
|
|
163
|
+
let retiring = false;
|
|
164
|
+
let idleTimer;
|
|
165
|
+
const flushing = /* @__PURE__ */ new Set();
|
|
166
|
+
const awaitingRequest = /* @__PURE__ */ new Set();
|
|
167
|
+
const endWith = (socket, frame) => {
|
|
168
|
+
const flushed = new Promise((resolve) => {
|
|
169
|
+
socket.once("close", () => resolve());
|
|
170
|
+
writeFrame(socket, frame);
|
|
171
|
+
socket.end(() => resolve());
|
|
172
|
+
});
|
|
173
|
+
flushing.add(flushed);
|
|
174
|
+
void flushed.then(() => flushing.delete(flushed));
|
|
175
|
+
};
|
|
176
|
+
let socketIno;
|
|
177
|
+
const ownsEndpoint = () => {
|
|
178
|
+
if (socketIno === void 0) return true;
|
|
179
|
+
try {
|
|
180
|
+
return fs.statSync(endpoint, { bigint: true, throwIfNoEntry: false })?.ino === socketIno;
|
|
181
|
+
} catch {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
const server = net.createServer((socket) => serveConnection(socket));
|
|
186
|
+
const exitOnceFlushed = () => void Promise.all(flushing).then(() => process.exit(0));
|
|
187
|
+
const stop = () => {
|
|
188
|
+
retiring = true;
|
|
189
|
+
if (idleTimer !== void 0) clearTimeout(idleTimer);
|
|
190
|
+
if (ownsEndpoint()) server.close();
|
|
191
|
+
for (const socket of awaitingRequest) endWith(socket, { t: "stale" });
|
|
192
|
+
awaitingRequest.clear();
|
|
193
|
+
if (!busy) exitOnceFlushed();
|
|
194
|
+
};
|
|
195
|
+
const armIdle = () => {
|
|
196
|
+
if (idleTimer !== void 0) clearTimeout(idleTimer);
|
|
197
|
+
idleTimer = setTimeout(stop, slot === 0 ? IDLE_EXIT_MS.primary : IDLE_EXIT_MS.overflow);
|
|
198
|
+
};
|
|
199
|
+
function serveConnection(socket) {
|
|
200
|
+
let nc = "";
|
|
201
|
+
let ns = "";
|
|
202
|
+
socket.setTimeout(HANDSHAKE_IDLE_MS, () => socket.destroy());
|
|
203
|
+
socket.on("error", () => socket.destroy());
|
|
204
|
+
socket.once("close", () => awaitingRequest.delete(socket));
|
|
205
|
+
const onMessage = (msg) => {
|
|
206
|
+
if (msg["t"] === "hello" && nc === "") {
|
|
207
|
+
if (msg["v"] !== PROTOCOL_VERSION || typeof msg["nc"] !== "string" || msg["nc"] === "") return void socket.destroy();
|
|
208
|
+
const reason = retiring ? "retiring" : retirementReason(loadedStamp);
|
|
209
|
+
if (reason !== void 0) {
|
|
210
|
+
if (reason === "disabled") touchMarker("disabled", configStamp());
|
|
211
|
+
if (reason === "bundle replaced") removeMarker(`spawn-${slot}`);
|
|
212
|
+
writeFrame(socket, { t: "stale" });
|
|
213
|
+
socket.end(() => {
|
|
214
|
+
if (!retiring) stop();
|
|
215
|
+
});
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (busy && msg["ctl"] !== true) {
|
|
219
|
+
writeFrame(socket, { t: "busy" });
|
|
220
|
+
return void socket.end();
|
|
221
|
+
}
|
|
222
|
+
nc = msg["nc"];
|
|
223
|
+
ns = nonce();
|
|
224
|
+
writeFrame(socket, { t: "challenge", v: PROTOCOL_VERSION, ns, mac: mac(key, "S", nc, ns) });
|
|
225
|
+
awaitingRequest.add(socket);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (msg["t"] === "req" && ns !== "") {
|
|
229
|
+
const body = msg["body"];
|
|
230
|
+
if (typeof body !== "string" || !macMatches(mac(key, "C", nc, ns, body), msg["mac"])) return void socket.destroy();
|
|
231
|
+
if (!awaitingRequest.delete(socket)) return;
|
|
232
|
+
let request;
|
|
233
|
+
let parseError;
|
|
234
|
+
try {
|
|
235
|
+
request = JSON.parse(body);
|
|
236
|
+
} catch (e) {
|
|
237
|
+
parseError = e;
|
|
238
|
+
}
|
|
239
|
+
const kind = request?.kind;
|
|
240
|
+
if (kind === "status" || kind === "stop") {
|
|
241
|
+
const resBody = JSON.stringify({ ok: true, info: { ...status } });
|
|
242
|
+
endWith(socket, { t: "res", mac: mac(key, "R", nc, ns, resBody), body: resBody });
|
|
243
|
+
if (kind === "stop" && !retiring) stop();
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (busy || retiring) {
|
|
247
|
+
writeFrame(socket, { t: retiring ? "stale" : "busy" });
|
|
248
|
+
return void socket.end();
|
|
249
|
+
}
|
|
250
|
+
busy = true;
|
|
251
|
+
socket.setTimeout(0);
|
|
252
|
+
let replied = false;
|
|
253
|
+
const reply = (res) => {
|
|
254
|
+
if (replied) return;
|
|
255
|
+
replied = true;
|
|
256
|
+
const resBody = JSON.stringify(res);
|
|
257
|
+
endWith(socket, { t: "res", mac: mac(key, "R", nc, ns, resBody), body: resBody });
|
|
258
|
+
};
|
|
259
|
+
void (async () => {
|
|
260
|
+
try {
|
|
261
|
+
if (request === void 0) throw parseError;
|
|
262
|
+
await handle(request, runCli, reply);
|
|
263
|
+
status.served++;
|
|
264
|
+
} catch (e) {
|
|
265
|
+
status.errors++;
|
|
266
|
+
reply({ ok: false, error: e instanceof Error ? e.message : String(e) });
|
|
267
|
+
}
|
|
268
|
+
busy = false;
|
|
269
|
+
status.lastUsedAt = Date.now();
|
|
270
|
+
if (retiring) stop();
|
|
271
|
+
else armIdle();
|
|
272
|
+
})();
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
socket.destroy();
|
|
276
|
+
};
|
|
277
|
+
readFrames(socket, onMessage, () => void 0);
|
|
278
|
+
}
|
|
279
|
+
if (!await listen(server, endpoint)) return;
|
|
280
|
+
if (process.platform !== "win32") socketIno = fs.statSync(endpoint, { bigint: true }).ino;
|
|
281
|
+
removeMarker("failed");
|
|
282
|
+
setInterval(() => {
|
|
283
|
+
if (!fs.existsSync(keyPath) || !ownsEndpoint()) stop();
|
|
284
|
+
}, KEY_CHECK_MS).unref();
|
|
285
|
+
if (process.platform !== "win32") {
|
|
286
|
+
try {
|
|
287
|
+
fs.chmodSync(endpoint, 384);
|
|
288
|
+
} catch {
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
armIdle();
|
|
292
|
+
}
|
|
293
|
+
export {
|
|
294
|
+
runHookServer
|
|
295
|
+
};
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
stripMultilineStringSpan,
|
|
11
11
|
stripNestedBlockCommentSpan,
|
|
12
12
|
stripStringLiterals
|
|
13
|
-
} from "./token-goat-chunk-
|
|
13
|
+
} from "./token-goat-chunk-7CPMDFGB.mjs";
|
|
14
14
|
import {
|
|
15
15
|
init_define_import_meta_env
|
|
16
16
|
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
@@ -25,10 +25,11 @@ import {
|
|
|
25
25
|
runSemantic,
|
|
26
26
|
runSkeleton,
|
|
27
27
|
runSymbol,
|
|
28
|
+
statThroughHandle,
|
|
28
29
|
withPinnedReads
|
|
29
|
-
} from "./token-goat-chunk-
|
|
30
|
-
import "./token-goat-chunk-
|
|
31
|
-
import "./token-goat-chunk-
|
|
30
|
+
} from "./token-goat-chunk-NMBWLRHW.mjs";
|
|
31
|
+
import "./token-goat-chunk-VZQEWRVH.mjs";
|
|
32
|
+
import "./token-goat-chunk-PQ53BSCF.mjs";
|
|
32
33
|
import {
|
|
33
34
|
buildProjectMap,
|
|
34
35
|
formatProjectMap,
|
|
@@ -37,59 +38,66 @@ import {
|
|
|
37
38
|
getProjectIndexCounts,
|
|
38
39
|
isWorkerRunning,
|
|
39
40
|
mapLookupBytesSaved
|
|
40
|
-
} from "./token-goat-chunk-
|
|
41
|
-
import "./token-goat-chunk-
|
|
42
|
-
import "./token-goat-chunk-
|
|
43
|
-
import "./token-goat-chunk-
|
|
44
|
-
import "./token-goat-chunk-
|
|
45
|
-
import "./token-goat-chunk-
|
|
41
|
+
} from "./token-goat-chunk-RTMVLHWX.mjs";
|
|
42
|
+
import "./token-goat-chunk-L7H3U27L.mjs";
|
|
43
|
+
import "./token-goat-chunk-RRNZMM3A.mjs";
|
|
44
|
+
import "./token-goat-chunk-E5TK5DNO.mjs";
|
|
45
|
+
import "./token-goat-chunk-ZER6EAXZ.mjs";
|
|
46
|
+
import "./token-goat-chunk-EUSDXRXU.mjs";
|
|
47
|
+
import "./token-goat-chunk-H5J3C56Q.mjs";
|
|
48
|
+
import "./token-goat-chunk-TDUT2CL6.mjs";
|
|
46
49
|
import {
|
|
47
50
|
claudeConfigDir
|
|
48
|
-
} from "./token-goat-chunk-
|
|
49
|
-
import "./token-goat-chunk-
|
|
50
|
-
import "./token-goat-chunk-
|
|
51
|
-
import "./token-goat-chunk-
|
|
52
|
-
import "./token-goat-chunk-
|
|
51
|
+
} from "./token-goat-chunk-ONXH6NZ5.mjs";
|
|
52
|
+
import "./token-goat-chunk-O6I2XU4P.mjs";
|
|
53
|
+
import "./token-goat-chunk-D4ETHJD6.mjs";
|
|
54
|
+
import "./token-goat-chunk-52NSDWYY.mjs";
|
|
55
|
+
import "./token-goat-chunk-2WOUYWLM.mjs";
|
|
53
56
|
import {
|
|
54
57
|
recordStat,
|
|
55
58
|
savedTokensFromBytes
|
|
56
|
-
} from "./token-goat-chunk-
|
|
57
|
-
import "./token-goat-chunk-
|
|
58
|
-
import "./token-goat-chunk-
|
|
59
|
+
} from "./token-goat-chunk-CIQ2FTY3.mjs";
|
|
60
|
+
import "./token-goat-chunk-SE6E4BKJ.mjs";
|
|
61
|
+
import "./token-goat-chunk-DNSPXQXQ.mjs";
|
|
59
62
|
import "./token-goat-chunk-3BTK54F3.mjs";
|
|
60
63
|
import "./token-goat-chunk-XTQAOTSO.mjs";
|
|
61
64
|
import "./token-goat-chunk-AH6QILZM.mjs";
|
|
62
|
-
import "./token-goat-chunk-
|
|
65
|
+
import "./token-goat-chunk-PGTH2U4C.mjs";
|
|
63
66
|
import {
|
|
64
67
|
checkEmbeddingPreflight,
|
|
65
68
|
embeddingsDepsAvailable
|
|
66
|
-
} from "./token-goat-chunk-
|
|
67
|
-
import "./token-goat-chunk-
|
|
69
|
+
} from "./token-goat-chunk-VMFWNHGR.mjs";
|
|
70
|
+
import "./token-goat-chunk-435UQTKD.mjs";
|
|
68
71
|
import {
|
|
69
72
|
getDb
|
|
70
|
-
} from "./token-goat-chunk-
|
|
73
|
+
} from "./token-goat-chunk-7CPMDFGB.mjs";
|
|
71
74
|
import {
|
|
72
|
-
envStrList,
|
|
73
75
|
loadConfig,
|
|
74
76
|
resolveProjectRoot
|
|
75
|
-
} from "./token-goat-chunk-
|
|
76
|
-
import "./token-goat-chunk-
|
|
77
|
-
import "./token-goat-chunk-
|
|
77
|
+
} from "./token-goat-chunk-TGOXNAHW.mjs";
|
|
78
|
+
import "./token-goat-chunk-XB5KKOCG.mjs";
|
|
79
|
+
import "./token-goat-chunk-YZAAZU2S.mjs";
|
|
78
80
|
import {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
extractErrorMessage
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
envStrList
|
|
82
|
+
} from "./token-goat-chunk-IVE6U7KV.mjs";
|
|
83
|
+
import {
|
|
84
|
+
extractErrorMessage
|
|
85
|
+
} from "./token-goat-chunk-XYWPOSCN.mjs";
|
|
86
|
+
import {
|
|
87
|
+
foldCaseForContainment
|
|
88
|
+
} from "./token-goat-chunk-TCQANXYC.mjs";
|
|
86
89
|
import {
|
|
87
90
|
displaySafeJson,
|
|
88
91
|
normalizePath
|
|
89
92
|
} from "./token-goat-chunk-NMTKNYGF.mjs";
|
|
93
|
+
import {
|
|
94
|
+
ENV_KEYS,
|
|
95
|
+
VERSION,
|
|
96
|
+
dataDir,
|
|
97
|
+
globalDbPath
|
|
98
|
+
} from "./token-goat-chunk-MELOKFDJ.mjs";
|
|
90
99
|
import "./token-goat-chunk-Y4AFKTHK.mjs";
|
|
91
|
-
import "./token-goat-chunk-
|
|
92
|
-
import "./token-goat-chunk-RRNZMM3A.mjs";
|
|
100
|
+
import "./token-goat-chunk-JTKCQMQA.mjs";
|
|
93
101
|
import {
|
|
94
102
|
init_define_import_meta_env
|
|
95
103
|
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
@@ -103,6 +111,7 @@ var TOKEN_GOAT_RETRY_RE = /token-goat (\w[\w-]*) "([^"]+)"/g;
|
|
|
103
111
|
var MCP_MAX_LIMIT = 1e3;
|
|
104
112
|
var MCP_MAX_CONTEXT_LINES = 50;
|
|
105
113
|
var MCP_MAX_OUTPUT_LINES = 1e4;
|
|
114
|
+
var MCP_MAX_MIN_LINES = 1e5;
|
|
106
115
|
var RETRY_PARAM_BY_COMMAND = {
|
|
107
116
|
read: "spec",
|
|
108
117
|
section: "spec",
|
|
@@ -221,6 +230,12 @@ function assertRootAllowed(resolvedRoot) {
|
|
|
221
230
|
}
|
|
222
231
|
var NO_CHECK_PINS = [];
|
|
223
232
|
function identityOf(p) {
|
|
233
|
+
try {
|
|
234
|
+
return fileIdentity(statThroughHandle(p));
|
|
235
|
+
} catch (err) {
|
|
236
|
+
const code = err.code;
|
|
237
|
+
if (code === "ENOENT" || code === "ENOTDIR") return null;
|
|
238
|
+
}
|
|
224
239
|
try {
|
|
225
240
|
return fileIdentity(fs.statSync(p, { bigint: true }));
|
|
226
241
|
} catch {
|
|
@@ -330,7 +345,7 @@ function mcpToolAllowlist() {
|
|
|
330
345
|
return names.length === 0 ? null : new Set(names);
|
|
331
346
|
}
|
|
332
347
|
async function createMcpServer() {
|
|
333
|
-
const [{ McpServer }, { z }] = await Promise.all([import("./token-goat-chunk-
|
|
348
|
+
const [{ McpServer }, { z }] = await Promise.all([import("./token-goat-chunk-6AK46ZT7.mjs"), import("./token-goat-chunk-CHLHM42P.mjs")]);
|
|
334
349
|
const server = new McpServer({ name: "token-goat", version: VERSION });
|
|
335
350
|
const allowlist = mcpToolAllowlist();
|
|
336
351
|
if (allowlist !== null) {
|
|
@@ -349,10 +364,7 @@ async function createMcpServer() {
|
|
|
349
364
|
}
|
|
350
365
|
}, 0).unref();
|
|
351
366
|
}
|
|
352
|
-
const
|
|
353
|
-
`absolute path to the workspace root to scope this ${verb} to; defaults to the MCP server process's cwd, which is not always the actual workspace root for MCP clients -- pass this explicitly when it might differ`
|
|
354
|
-
);
|
|
355
|
-
const projectRootField = makeProjectRootField("lookup");
|
|
367
|
+
const projectRootField = z.string().optional().describe("absolute workspace root; defaults to the server's cwd, which may not be the workspace, so pass it when unsure");
|
|
356
368
|
server.registerTool(
|
|
357
369
|
"symbol",
|
|
358
370
|
{
|
|
@@ -396,9 +408,9 @@ async function createMcpServer() {
|
|
|
396
408
|
server.registerTool(
|
|
397
409
|
"read",
|
|
398
410
|
{
|
|
399
|
-
description: "Read
|
|
411
|
+
description: "Read a symbol's full body (file::symbol), several from one file (file::a,b), a line range (file@N-M, file@N), or a file.",
|
|
400
412
|
inputSchema: {
|
|
401
|
-
spec: z.string().describe("file::symbol, file@N-M, file@N, a
|
|
413
|
+
spec: z.string().describe("file::symbol, file::a,b, file@N-M, file@N, or a file path"),
|
|
402
414
|
json: z.boolean().optional().describe("output as JSON"),
|
|
403
415
|
forceRefresh: z.boolean().optional().describe("reparse file from disk before querying (ignore stale index)"),
|
|
404
416
|
stats: z.boolean().optional().describe("add per-symbol reference count and doc-coverage flag"),
|
|
@@ -461,7 +473,7 @@ async function createMcpServer() {
|
|
|
461
473
|
inputSchema: {
|
|
462
474
|
file: z.string().describe("file path"),
|
|
463
475
|
json: z.boolean().optional().describe("output as JSON"),
|
|
464
|
-
minLines: z.number().int().optional().describe("only show symbols at least N lines long"),
|
|
476
|
+
minLines: z.number().int().nonnegative().max(MCP_MAX_MIN_LINES).optional().describe("only show symbols at least N lines long"),
|
|
465
477
|
forceRefresh: z.boolean().optional().describe("reparse file from disk before querying (ignore stale index)"),
|
|
466
478
|
stats: z.boolean().optional().describe("add per-symbol reference count and doc-coverage flag"),
|
|
467
479
|
projectRoot: projectRootField
|
|
@@ -495,7 +507,7 @@ async function createMcpServer() {
|
|
|
495
507
|
inputSchema: {
|
|
496
508
|
file: z.string().describe("file path"),
|
|
497
509
|
json: z.boolean().optional().describe("output as JSON"),
|
|
498
|
-
minLines: z.number().int().optional().describe("only show symbols at least N lines long"),
|
|
510
|
+
minLines: z.number().int().nonnegative().max(MCP_MAX_MIN_LINES).optional().describe("only show symbols at least N lines long"),
|
|
499
511
|
forceRefresh: z.boolean().optional().describe("reparse file from disk before querying (ignore stale index)"),
|
|
500
512
|
stats: z.boolean().optional().describe("add per-symbol reference count and doc-coverage flag"),
|
|
501
513
|
projectRoot: projectRootField
|
|
@@ -525,16 +537,16 @@ async function createMcpServer() {
|
|
|
525
537
|
server.registerTool(
|
|
526
538
|
"semantic",
|
|
527
539
|
{
|
|
528
|
-
description: "Semantic search over the indexed project
|
|
540
|
+
description: "Semantic search over the indexed project; falls back to full-text search without an embedding index.",
|
|
529
541
|
inputSchema: {
|
|
530
542
|
query: z.string().describe("natural-language search query"),
|
|
531
543
|
limit: z.number().int().positive().max(MCP_MAX_LIMIT).optional().describe("max results (default: 20)"),
|
|
532
|
-
grep: z.string().optional().describe("
|
|
533
|
-
excludeTests: z.boolean().optional().describe("hide hits
|
|
534
|
-
preflight: z.boolean().optional().describe("
|
|
535
|
-
warm: z.boolean().optional().describe("
|
|
544
|
+
grep: z.string().optional().describe("only hits whose file path matches this regex (a literal substring if it is not valid regex)"),
|
|
545
|
+
excludeTests: z.boolean().optional().describe("hide hits in test files"),
|
|
546
|
+
preflight: z.boolean().optional().describe("report whether embeddings are ready, instead of searching"),
|
|
547
|
+
warm: z.boolean().optional().describe("load the embedding model before the query"),
|
|
536
548
|
json: z.boolean().optional().describe("output as JSON"),
|
|
537
|
-
projectRoot:
|
|
549
|
+
projectRoot: projectRootField
|
|
538
550
|
},
|
|
539
551
|
// openWorldHint stays false although a first call on a machine with no cached model downloads one over the network: what this tool interacts with is the local index, and the download provisions the tool rather than being the tool reaching out. A client reading `true` here would take it as "this searches the internet", which is the wrong warning.
|
|
540
552
|
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
@@ -558,9 +570,9 @@ async function createMcpServer() {
|
|
|
558
570
|
server.registerTool(
|
|
559
571
|
"index_status",
|
|
560
572
|
{
|
|
561
|
-
description: '
|
|
573
|
+
description: 'Whether the project index can be trusted now: indexed at all, file and symbol counts, reindex queue depth, worker alive, and embeddings available (without them semantic falls back to full-text search). Call it when another token-goat tool returns nothing, to tell "no match" from "index not ready".',
|
|
562
574
|
inputSchema: {
|
|
563
|
-
projectRoot:
|
|
575
|
+
projectRoot: projectRootField
|
|
564
576
|
},
|
|
565
577
|
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
566
578
|
},
|
|
@@ -620,13 +632,13 @@ async function createMcpServer() {
|
|
|
620
632
|
server.registerTool(
|
|
621
633
|
"refs",
|
|
622
634
|
{
|
|
623
|
-
description: "Find references to
|
|
635
|
+
description: "Find references to symbols. An unambiguous TypeScript symbol is type-resolved, dropping same-named symbols; anything else matches by name.",
|
|
624
636
|
inputSchema: {
|
|
625
|
-
spec: z.string().describe("file::symbol, symbol,
|
|
637
|
+
spec: z.string().describe("file::symbol, symbol, a,b,c, or file::a,b"),
|
|
626
638
|
callers: z.boolean().optional().describe("group references by their enclosing caller symbol"),
|
|
627
639
|
limit: z.number().int().positive().max(MCP_MAX_LIMIT).optional().describe("max results"),
|
|
628
640
|
top: z.number().int().positive().max(MCP_MAX_LIMIT).optional().describe(
|
|
629
|
-
"
|
|
641
|
+
"list only the top N files by reference count, instead of every reference"
|
|
630
642
|
),
|
|
631
643
|
json: z.boolean().optional().describe("output as JSON"),
|
|
632
644
|
projectRoot: projectRootField
|
|
@@ -656,15 +668,15 @@ async function createMcpServer() {
|
|
|
656
668
|
server.registerTool(
|
|
657
669
|
"brief",
|
|
658
670
|
{
|
|
659
|
-
description: "
|
|
671
|
+
description: "Understand a symbol in one call: signature, location, token count, body, callers and containing doc section. Prefer it to read plus refs. Spec file::symbol, file::a,b or a.ts::x,b.ts::y; a bare name without a file is not accepted.",
|
|
660
672
|
inputSchema: {
|
|
661
|
-
spec: z.string().describe("file::symbol
|
|
673
|
+
spec: z.string().describe("file::symbol, file::a,b, or a.ts::x,b.ts::y"),
|
|
662
674
|
limit: z.number().int().positive().max(MCP_MAX_LIMIT).optional().describe("max callers to show (default: 20)"),
|
|
663
675
|
json: z.boolean().optional().describe("output as JSON"),
|
|
664
|
-
context: z.number().int().nonnegative().max(MCP_MAX_CONTEXT_LINES).optional().describe("
|
|
665
|
-
excludeTests: z.boolean().optional().describe("hide callers
|
|
666
|
-
grep: z.string().optional().describe("only
|
|
667
|
-
projectRoot:
|
|
676
|
+
context: z.number().int().nonnegative().max(MCP_MAX_CONTEXT_LINES).optional().describe("call-site lines to show around each caller (default 0)"),
|
|
677
|
+
excludeTests: z.boolean().optional().describe("hide callers in test files"),
|
|
678
|
+
grep: z.string().optional().describe("only callers whose enclosing symbol matches this regex (a literal substring if it is not valid regex)"),
|
|
679
|
+
projectRoot: projectRootField
|
|
668
680
|
},
|
|
669
681
|
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
670
682
|
},
|
|
@@ -695,7 +707,7 @@ async function createMcpServer() {
|
|
|
695
707
|
description: "Project overview: file count, languages, headline symbols, and recently modified files.",
|
|
696
708
|
inputSchema: {
|
|
697
709
|
compact: z.boolean().optional().describe("compact, low-token summary"),
|
|
698
|
-
projectRoot:
|
|
710
|
+
projectRoot: projectRootField
|
|
699
711
|
},
|
|
700
712
|
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
701
713
|
},
|
|
@@ -744,7 +756,7 @@ async function createMcpServer() {
|
|
|
744
756
|
recursive: z.boolean().optional().describe("descend into subdirectories (default: true)"),
|
|
745
757
|
context: z.number().int().nonnegative().max(MCP_MAX_CONTEXT_LINES).optional().describe("lines of context to show before and after each match"),
|
|
746
758
|
// runGrep takes no projectRoot of its own (its `path` array is its scope), so this field only names the root the confinement check is made against -- without it, a search rooted anywhere but the server process's cwd is refused.
|
|
747
|
-
projectRoot:
|
|
759
|
+
projectRoot: projectRootField
|
|
748
760
|
},
|
|
749
761
|
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
750
762
|
},
|
|
@@ -851,7 +863,7 @@ async function createMcpServer() {
|
|
|
851
863
|
inputSchema: {
|
|
852
864
|
name: z.string().regex(/^[A-Za-z0-9._-]{1,128}$/).describe("handoff name"),
|
|
853
865
|
text: z.string().max(CONTENT_MAX_INPUT_CHARS).describe("handoff text"),
|
|
854
|
-
projectRoot:
|
|
866
|
+
projectRoot: projectRootField
|
|
855
867
|
},
|
|
856
868
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false }
|
|
857
869
|
},
|
|
@@ -867,7 +879,7 @@ async function createMcpServer() {
|
|
|
867
879
|
inputSchema: {
|
|
868
880
|
name: z.string().regex(/^[A-Za-z0-9._-]{1,128}$/).describe("handoff name"),
|
|
869
881
|
full: z.boolean().optional().describe("return full text instead of a compact payload"),
|
|
870
|
-
projectRoot:
|
|
882
|
+
projectRoot: projectRootField
|
|
871
883
|
},
|
|
872
884
|
// Reads like a read, and is not one: resolving compactly runs the handoff text back through compressText, which stores the compact payload so the recovery id it hands back can be redeemed. A measurement, not a reading of this code -- the guard hashes the store's bytes around every tool call, and this is the tool it caught.
|
|
873
885
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false }
|
|
@@ -2,7 +2,7 @@ import { createRequire as __cjsRequire } from 'node:module';
|
|
|
2
2
|
const require = __cjsRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
Database
|
|
5
|
-
} from "./token-goat-chunk-
|
|
5
|
+
} from "./token-goat-chunk-XB5KKOCG.mjs";
|
|
6
6
|
import {
|
|
7
7
|
displaySafeText
|
|
8
8
|
} from "./token-goat-chunk-NMTKNYGF.mjs";
|
|
@@ -3,7 +3,7 @@ const require = __cjsRequire(import.meta.url);
|
|
|
3
3
|
import {
|
|
4
4
|
queryCsv,
|
|
5
5
|
quoteCsvCell
|
|
6
|
-
} from "./token-goat-chunk-
|
|
6
|
+
} from "./token-goat-chunk-DNSPXQXQ.mjs";
|
|
7
7
|
import {
|
|
8
8
|
NotAnOfficeDocumentError,
|
|
9
9
|
assertOoxmlWithinDeadline,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
ooxmlWorkDeadline,
|
|
13
13
|
parseOoxmlPart,
|
|
14
14
|
readOoxmlZip
|
|
15
|
-
} from "./token-goat-chunk-
|
|
15
|
+
} from "./token-goat-chunk-UXSXQQIY.mjs";
|
|
16
16
|
import {
|
|
17
17
|
displaySafeText
|
|
18
18
|
} from "./token-goat-chunk-NMTKNYGF.mjs";
|