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.
Files changed (77) hide show
  1. package/README.md +2 -0
  2. package/dist/{token-goat-chunk-OZRSREKR.mjs → token-goat-chunk-2AWQ2R5X.mjs} +2 -2
  3. package/dist/{token-goat-chunk-5NNYIUGV.mjs → token-goat-chunk-2NNUA2LR.mjs} +4 -4
  4. package/dist/{token-goat-chunk-4RN64ZND.mjs → token-goat-chunk-2WOUYWLM.mjs} +2 -1
  5. package/dist/{token-goat-chunk-HUDC5GS5.mjs → token-goat-chunk-435UQTKD.mjs} +5 -3
  6. package/dist/{token-goat-chunk-6DQNNFJ6.mjs → token-goat-chunk-44BM7DDQ.mjs} +3 -3
  7. package/dist/{token-goat-chunk-4JMWPWCS.mjs → token-goat-chunk-52NSDWYY.mjs} +2 -2
  8. package/dist/{token-goat-chunk-IHKZ3QNA.mjs → token-goat-chunk-67BNIKKO.mjs} +19 -16
  9. package/dist/{token-goat-chunk-XBESNWEX.mjs → token-goat-chunk-6AK46ZT7.mjs} +2 -3
  10. package/dist/{token-goat-chunk-M56BWPBN.mjs → token-goat-chunk-7CPMDFGB.mjs} +166 -40
  11. package/dist/token-goat-chunk-ASLWOQ3I.mjs +14 -0
  12. package/dist/{token-goat-chunk-QM76S6YS.mjs → token-goat-chunk-BGYOZ6DO.mjs} +6 -4
  13. package/dist/{token-goat-chunk-JXK2HQXS.mjs → token-goat-chunk-C5YPNZKQ.mjs} +3 -3
  14. package/dist/{token-goat-chunk-MVSWBNMD.mjs → token-goat-chunk-CIQ2FTY3.mjs} +19 -14
  15. package/dist/{token-goat-chunk-BJBRGPBX.mjs → token-goat-chunk-D4ETHJD6.mjs} +6 -4
  16. package/dist/{token-goat-chunk-VE27HPIF.mjs → token-goat-chunk-DNRPXHYH.mjs} +21 -17
  17. package/dist/{token-goat-chunk-YWSP6IU7.mjs → token-goat-chunk-DNSPXQXQ.mjs} +2 -2
  18. package/dist/token-goat-chunk-DPNLUJWB.mjs +220 -0
  19. package/dist/{token-goat-chunk-I7CB3X4K.mjs → token-goat-chunk-E4ZOJIZK.mjs} +10 -7
  20. package/dist/{token-goat-chunk-IZXKVT4A.mjs → token-goat-chunk-E5TK5DNO.mjs} +11 -4
  21. package/dist/{token-goat-chunk-MMLMALWK.mjs → token-goat-chunk-EUSDXRXU.mjs} +60 -12
  22. package/dist/{token-goat-chunk-7R2XYKC5.mjs → token-goat-chunk-FTP4U4QA.mjs} +12 -9
  23. package/dist/{token-goat-chunk-LEG3JNJ6.mjs → token-goat-chunk-G23DWHV4.mjs} +17 -14
  24. package/dist/{token-goat-chunk-L7SDVGBT.mjs → token-goat-chunk-G7IWXCFF.mjs} +49 -23
  25. package/dist/{token-goat-chunk-NILVK7XM.mjs → token-goat-chunk-GLXRTTLE.mjs} +7 -5
  26. package/dist/{token-goat-chunk-6CCQDAYY.mjs → token-goat-chunk-H5J3C56Q.mjs} +35 -16
  27. package/dist/{token-goat-chunk-Q4S3UQGO.mjs → token-goat-chunk-HNFZZHFW.mjs} +2 -2
  28. package/dist/{token-goat-chunk-CBMY2FGI.mjs → token-goat-chunk-HUYUHODZ.mjs} +572 -230
  29. package/dist/token-goat-chunk-IVE6U7KV.mjs +53 -0
  30. package/dist/{token-goat-chunk-F7QZRIWM.mjs → token-goat-chunk-IVWI2OCK.mjs} +8 -30
  31. package/dist/{token-goat-chunk-GMOUBOX4.mjs → token-goat-chunk-JTKCQMQA.mjs} +37 -5
  32. package/dist/{token-goat-chunk-6SGLIPQB.mjs → token-goat-chunk-KOPIR3KZ.mjs} +12 -9
  33. package/dist/token-goat-chunk-L7H3U27L.mjs +35 -0
  34. package/dist/{token-goat-chunk-FSTWAOW6.mjs → token-goat-chunk-LZNBQTDK.mjs} +6 -4
  35. package/dist/token-goat-chunk-MELOKFDJ.mjs +199 -0
  36. package/dist/{token-goat-chunk-VWZKZPSR.mjs → token-goat-chunk-NMBWLRHW.mjs} +76 -39
  37. package/dist/{token-goat-chunk-HXNAC4ZF.mjs → token-goat-chunk-O6I2XU4P.mjs} +12 -10
  38. package/dist/{token-goat-chunk-MAMQPC43.mjs → token-goat-chunk-ONXH6NZ5.mjs} +1 -1
  39. package/dist/token-goat-chunk-ORNFMIER.mjs +295 -0
  40. package/dist/{token-goat-chunk-66LODAUT.mjs → token-goat-chunk-PGTH2U4C.mjs} +1 -1
  41. package/dist/{token-goat-chunk-SJEKA7Y2.mjs → token-goat-chunk-PKRWMHVP.mjs} +76 -64
  42. package/dist/{token-goat-chunk-DA43OE7L.mjs → token-goat-chunk-PQ53BSCF.mjs} +1 -1
  43. package/dist/{token-goat-chunk-RSS3TLXU.mjs → token-goat-chunk-PYSUADX4.mjs} +2 -2
  44. package/dist/{token-goat-chunk-EL7M26WP.mjs → token-goat-chunk-QO3LXVVR.mjs} +185 -104
  45. package/dist/{token-goat-chunk-XI2VFAV6.mjs → token-goat-chunk-RLP6J7WR.mjs} +6 -6
  46. package/dist/token-goat-chunk-RQGGMPCR.mjs +205 -0
  47. package/dist/{token-goat-chunk-6Z5ULNE5.mjs → token-goat-chunk-RTMVLHWX.mjs} +165 -60
  48. package/dist/{token-goat-chunk-E3K3BTEQ.mjs → token-goat-chunk-S4VSXURL.mjs} +8 -6
  49. package/dist/{token-goat-chunk-LKSXAMJB.mjs → token-goat-chunk-SE6E4BKJ.mjs} +1 -1
  50. package/dist/token-goat-chunk-TCQANXYC.mjs +351 -0
  51. package/dist/{token-goat-chunk-GGLEE35R.mjs → token-goat-chunk-TDUT2CL6.mjs} +7 -7
  52. package/dist/{token-goat-chunk-CC2PYJM7.mjs → token-goat-chunk-TGOXNAHW.mjs} +54 -112
  53. package/dist/{token-goat-chunk-XKY4VKJ4.mjs → token-goat-chunk-UA5BKWWQ.mjs} +1 -1
  54. package/dist/{token-goat-chunk-UBUKHVYW.mjs → token-goat-chunk-UXSXQQIY.mjs} +1 -1
  55. package/dist/{token-goat-chunk-D5ICEPSB.mjs → token-goat-chunk-VMFWNHGR.mjs} +79 -68
  56. package/dist/token-goat-chunk-VQ6F6T7X.mjs +36 -0
  57. package/dist/{token-goat-chunk-4STDIGYC.mjs → token-goat-chunk-VZQEWRVH.mjs} +6 -4
  58. package/dist/{token-goat-chunk-OSUFN2FV.mjs → token-goat-chunk-XB5KKOCG.mjs} +5 -25
  59. package/dist/{token-goat-chunk-L45ZQRT7.mjs → token-goat-chunk-XYWPOSCN.mjs} +57 -615
  60. package/dist/{token-goat-chunk-4JJBFT7V.mjs → token-goat-chunk-YAGLESS3.mjs} +8 -5
  61. package/dist/token-goat-chunk-YKSRAWUU.mjs +33 -0
  62. package/dist/{token-goat-chunk-F2ARFHLJ.mjs → token-goat-chunk-YOOVFPTP.mjs} +2 -2
  63. package/dist/{token-goat-chunk-EEIDFMEM.mjs → token-goat-chunk-YZAAZU2S.mjs} +12 -3
  64. package/dist/token-goat-chunk-Z6KBMOBI.mjs +53 -0
  65. package/dist/{token-goat-chunk-RJH64KQH.mjs → token-goat-chunk-ZER6EAXZ.mjs} +3 -3
  66. package/dist/token-goat-hook-client.cjs +475 -0
  67. package/dist/token-goat-hook-client.mjs +26 -0
  68. package/dist/token-goat-hook.mjs +31 -27
  69. package/dist/token-goat.core.mjs +9 -44
  70. package/docs/C4_RUNTIME_ARCHITECTURE.md +2 -2
  71. package/docs/cli.md +3 -2
  72. package/docs/install.md +16 -14
  73. package/package.json +1 -1
  74. package/dist/token-goat-chunk-7MAFDRVR.mjs +0 -47
  75. package/dist/token-goat-chunk-BCN2YQC6.mjs +0 -32
  76. package/dist/token-goat-chunk-D7GHQKQD.mjs +0 -30
  77. 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-M56BWPBN.mjs";
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-VWZKZPSR.mjs";
30
- import "./token-goat-chunk-4STDIGYC.mjs";
31
- import "./token-goat-chunk-DA43OE7L.mjs";
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-6Z5ULNE5.mjs";
41
- import "./token-goat-chunk-IZXKVT4A.mjs";
42
- import "./token-goat-chunk-RJH64KQH.mjs";
43
- import "./token-goat-chunk-MMLMALWK.mjs";
44
- import "./token-goat-chunk-6CCQDAYY.mjs";
45
- import "./token-goat-chunk-GGLEE35R.mjs";
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-MAMQPC43.mjs";
49
- import "./token-goat-chunk-HXNAC4ZF.mjs";
50
- import "./token-goat-chunk-BJBRGPBX.mjs";
51
- import "./token-goat-chunk-4JMWPWCS.mjs";
52
- import "./token-goat-chunk-4RN64ZND.mjs";
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-MVSWBNMD.mjs";
57
- import "./token-goat-chunk-LKSXAMJB.mjs";
58
- import "./token-goat-chunk-YWSP6IU7.mjs";
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-66LODAUT.mjs";
65
+ import "./token-goat-chunk-PGTH2U4C.mjs";
63
66
  import {
64
67
  checkEmbeddingPreflight,
65
68
  embeddingsDepsAvailable
66
- } from "./token-goat-chunk-D5ICEPSB.mjs";
67
- import "./token-goat-chunk-HUDC5GS5.mjs";
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-M56BWPBN.mjs";
73
+ } from "./token-goat-chunk-7CPMDFGB.mjs";
71
74
  import {
72
- envStrList,
73
75
  loadConfig,
74
76
  resolveProjectRoot
75
- } from "./token-goat-chunk-CC2PYJM7.mjs";
76
- import "./token-goat-chunk-EEIDFMEM.mjs";
77
- import "./token-goat-chunk-OSUFN2FV.mjs";
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
- ENV_KEYS,
80
- VERSION,
81
- dataDir,
82
- extractErrorMessage,
83
- foldCaseForContainment,
84
- globalDbPath
85
- } from "./token-goat-chunk-L45ZQRT7.mjs";
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-GMOUBOX4.mjs";
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-XBESNWEX.mjs"), import("./token-goat-chunk-CHLHM42P.mjs")]);
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 makeProjectRootField = (verb) => z.string().optional().describe(
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 one symbol's full body, given a spec of the form file::symbol, or a line range file@N-M / file@N, or a bare file path. Pass a comma-separated spec (file::a,b) to fetch several symbols' bodies from one file in a single call.",
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 bare file path, or comma-separated file::a,b for a merged multi-symbol view"),
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 (falls back to full-text search when no embedding index is available). Scoped to projectRoot if given, else the MCP server process's own cwd -- which may not be the actual workspace root for a client that launched the server from elsewhere, so pass projectRoot explicitly when in doubt.",
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("filter to hits whose file path matches this regex (literal substring if it does not compile as regex); matched against the path as rendered, same convention as refs --grep"),
533
- excludeTests: z.boolean().optional().describe("hide hits whose file is a test file (opt-in; default output is unchanged)"),
534
- preflight: z.boolean().optional().describe("run semantic embedding preflight check and return status"),
535
- warm: z.boolean().optional().describe("warm up the embedding model session in memory before query execution"),
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: makeProjectRootField("search")
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: 'Report whether the index for a project can be trusted right now: whether it has ever been indexed at all, current file/symbol counts, dirty-reindex-queue depth, whether the background worker is alive, and whether embeddings are available (semantic silently degrades to full-text search without them). Call this after an unexpectedly empty result from another token-goat tool (symbol/read/semantic/refs/brief/...) to tell apart "no match" from "the index is not ready yet" -- an MCP-only client has no hook layer to warn about this on its own, so an empty tool result and a stale/unindexed project look identical without this check.',
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: makeProjectRootField("check")
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 one or more symbols (spec: file::symbol, symbol, or comma-separated a,b,c / file::a,b for a merged multi-symbol view). For an unambiguous TypeScript symbol, automatically type-resolves candidates via the TypeScript compiler API to drop same-named-different-symbol false positives; falls back to name-based matching when that is not possible.",
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, or comma-separated a,b,c / file::a,b for a merged multi-symbol view"),
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
- "for a high-fanout symbol, group references by file (count only) and show only the top N files by reference count instead of a per-line dump"
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: "One-shot symbol orientation: signature, location, token count, body, callers, and containing doc section, in a single call (spec: file::symbol; comma-separated file::a,b for a merged multi-symbol view; cross-file a.ts::x,b.ts::y is also supported -- unlike refs, a bare symbol name with no file is not accepted). Prefer this over separate read + refs calls when the goal is to understand a symbol, not just fetch its source: it folds the work of read (body) and refs --callers (call sites) into one result, at a fraction of the combined round-trip cost.",
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; comma-separated file::a,b for a merged multi-symbol view; cross-file a.ts::x,b.ts::y is also supported"),
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("lines of call-site source to show before and after each caller (default 0)"),
665
- excludeTests: z.boolean().optional().describe("hide callers whose call site lives in a test file (opt-in; default output is unchanged)"),
666
- grep: z.string().optional().describe("only show callers whose enclosing symbol name matches this regex (literal substring if it is not valid regex)"),
667
- projectRoot: makeProjectRootField("orient")
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: makeProjectRootField("overview")
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: makeProjectRootField("search")
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: makeProjectRootField("scope")
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: makeProjectRootField("scope")
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-OSUFN2FV.mjs";
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-YWSP6IU7.mjs";
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-UBUKHVYW.mjs";
15
+ } from "./token-goat-chunk-UXSXQQIY.mjs";
16
16
  import {
17
17
  displaySafeText
18
18
  } from "./token-goat-chunk-NMTKNYGF.mjs";