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,205 @@
1
+ import { createRequire as __cjsRequire } from 'node:module';
2
+ const require = __cjsRequire(import.meta.url);
3
+ import {
4
+ PROTOCOL_VERSION,
5
+ SERVER_SLOTS,
6
+ configStamp,
7
+ encodeFrame,
8
+ endpointFor,
9
+ envSnapshot,
10
+ frameFits,
11
+ launcherPath,
12
+ mac,
13
+ macMatches,
14
+ markerAgeMs,
15
+ nonce,
16
+ readFrames,
17
+ readMarker,
18
+ readServerKey,
19
+ touchMarker,
20
+ writeFrame
21
+ } from "./token-goat-chunk-DPNLUJWB.mjs";
22
+ import {
23
+ envBool
24
+ } from "./token-goat-chunk-IVE6U7KV.mjs";
25
+ import {
26
+ init_define_import_meta_env
27
+ } from "./token-goat-chunk-A37V4PBF.mjs";
28
+
29
+ // src/hook_client.ts
30
+ init_define_import_meta_env();
31
+ import { spawn } from "node:child_process";
32
+ import * as fs from "node:fs";
33
+ import * as net from "node:net";
34
+ var HANDSHAKE_TIMEOUT_MS = 150;
35
+ var FIND_BUDGET_MS = 300;
36
+ var RESPONSE_TIMEOUT_MS = 12e4;
37
+ var CONTROL_WAIT_MS = 1e4;
38
+ var SPAWN_RETRY_MS = 3e4;
39
+ var DISABLED_MARKER_TTL_MS = 10 * 6e4;
40
+ function attempt(slot, key, request, handshakeMs, dir) {
41
+ return new Promise((resolve) => {
42
+ const socket = net.connect(endpointFor(slot, dir));
43
+ const nc = nonce();
44
+ let dispatched = false;
45
+ let settled = false;
46
+ const finish = (outcome) => {
47
+ if (settled) return;
48
+ settled = true;
49
+ clearTimeout(timer);
50
+ socket.destroy();
51
+ resolve(outcome);
52
+ };
53
+ let timer = setTimeout(() => finish({ kind: "busy" }), handshakeMs);
54
+ socket.on("error", (e) => {
55
+ if (dispatched) finish({ kind: "lost" });
56
+ else finish({ kind: e.code === "ENOENT" || e.code === "ECONNREFUSED" ? "absent" : "refused" });
57
+ });
58
+ socket.on("close", () => finish({ kind: dispatched ? "lost" : "refused" }));
59
+ const control = request.kind === "status" || request.kind === "stop";
60
+ socket.on("connect", () => writeFrame(socket, { t: "hello", v: PROTOCOL_VERSION, nc, ...control ? { ctl: true } : {} }));
61
+ let ns = "";
62
+ readFrames(
63
+ socket,
64
+ (msg) => {
65
+ if (msg["t"] === "busy") return finish({ kind: "busy" });
66
+ if (msg["t"] === "stale") return finish({ kind: "stale" });
67
+ if (msg["t"] === "challenge" && !dispatched) {
68
+ ns = typeof msg["ns"] === "string" ? msg["ns"] : "";
69
+ if (ns === "" || msg["v"] !== PROTOCOL_VERSION || !macMatches(mac(key, "S", nc, ns), msg["mac"])) return finish({ kind: "refused" });
70
+ const body = JSON.stringify(request);
71
+ const frame = encodeFrame({ t: "req", mac: mac(key, "C", nc, ns, body), body });
72
+ if (!frameFits(frame)) return finish({ kind: "oversize" });
73
+ dispatched = true;
74
+ clearTimeout(timer);
75
+ timer = setTimeout(() => finish({ kind: "lost" }), RESPONSE_TIMEOUT_MS);
76
+ socket.write(frame);
77
+ return;
78
+ }
79
+ if (msg["t"] === "res" && dispatched) {
80
+ const body = msg["body"];
81
+ if (typeof body !== "string" || !macMatches(mac(key, "R", nc, ns, body), msg["mac"])) return finish({ kind: "lost" });
82
+ try {
83
+ return finish({ kind: "served", reply: JSON.parse(body) });
84
+ } catch {
85
+ return finish({ kind: "lost" });
86
+ }
87
+ }
88
+ finish({ kind: dispatched ? "lost" : "refused" });
89
+ },
90
+ () => finish({ kind: dispatched ? "lost" : "refused" })
91
+ );
92
+ });
93
+ }
94
+ function startServer(slot) {
95
+ const launcher = launcherPath();
96
+ const disabled = markerAgeMs("disabled") < DISABLED_MARKER_TTL_MS && readMarker("disabled") === configStamp();
97
+ if (disabled || markerAgeMs(`spawn-${slot}`) < SPAWN_RETRY_MS || !fs.existsSync(launcher)) return;
98
+ touchMarker(`spawn-${slot}`);
99
+ try {
100
+ spawn(process.execPath, [launcher, "hook-server", "run", "--slot", String(slot)], { detached: true, stdio: "ignore", windowsHide: true }).unref();
101
+ } catch {
102
+ }
103
+ }
104
+ function serverEnabled() {
105
+ return envBool("TOKEN_GOAT_HOOK_SERVER", true);
106
+ }
107
+ async function callServer(request, opts = {}) {
108
+ if (!serverEnabled()) return void 0;
109
+ const autostart = opts.autostart !== false;
110
+ const key = readServerKey();
111
+ if (key === void 0) {
112
+ if (autostart) startServer(0);
113
+ return void 0;
114
+ }
115
+ const deadline = Date.now() + FIND_BUDGET_MS;
116
+ for (let slot = 0; slot < SERVER_SLOTS && Date.now() < deadline; slot++) {
117
+ const outcome = await attempt(slot, key, request, opts.handshakeMs ?? HANDSHAKE_TIMEOUT_MS);
118
+ if (outcome.kind === "served") return outcome.reply;
119
+ if (outcome.kind === "lost") return "lost";
120
+ if (outcome.kind === "absent") {
121
+ if (autostart) startServer(slot);
122
+ return void 0;
123
+ }
124
+ if (outcome.kind === "stale" || outcome.kind === "oversize") return void 0;
125
+ }
126
+ return void 0;
127
+ }
128
+ async function relayViaServer(event, input, harnessWaitMs) {
129
+ try {
130
+ const request = {
131
+ kind: "hook",
132
+ event,
133
+ input: typeof input === "string" ? input : JSON.stringify(input),
134
+ elapsedMs: performance.now(),
135
+ env: envSnapshot(),
136
+ cwd: process.cwd()
137
+ };
138
+ if (harnessWaitMs !== void 0) request.harnessWaitMs = harnessWaitMs;
139
+ const reply = await callServer(request);
140
+ if (reply === void 0) return void 0;
141
+ if (reply === "lost" || !reply.ok || !("stdout" in reply)) return "{}";
142
+ return reply.stdout;
143
+ } catch {
144
+ return void 0;
145
+ }
146
+ }
147
+ var WARM_CLI_COMMANDS = /* @__PURE__ */ new Set([
148
+ "answer",
149
+ "brief",
150
+ "changed",
151
+ "exports",
152
+ "imports",
153
+ "map",
154
+ "outline",
155
+ "read",
156
+ "refs",
157
+ "section",
158
+ "semantic",
159
+ "skeleton",
160
+ "symbol"
161
+ ]);
162
+ function warmCliEligible(argv) {
163
+ const command = argv[2];
164
+ if (command === void 0 || !WARM_CLI_COMMANDS.has(command) || process.stdout.isTTY === true) return false;
165
+ return !argv.slice(3).some((a) => a === "-" || a === "--stdin" || a === "--help" || a === "-h");
166
+ }
167
+ async function runCliViaServer(argv) {
168
+ if (!warmCliEligible(argv)) return false;
169
+ try {
170
+ const reply = await callServer({ kind: "cli", argv: argv.slice(2), env: envSnapshot(), cwd: process.cwd() });
171
+ if (reply === void 0 || reply === "lost" || !reply.ok || !("stdout" in reply)) return false;
172
+ if (reply.stdout !== "") process.stdout.write(reply.stdout);
173
+ if (reply.stderr !== void 0 && reply.stderr !== "") process.stderr.write(reply.stderr);
174
+ process.exitCode = reply.status ?? 0;
175
+ return true;
176
+ } catch {
177
+ return false;
178
+ }
179
+ }
180
+ async function serverStatuses(dir) {
181
+ return (await queryServers("status", dir)).flatMap(({ reply }) => reply.ok && "info" in reply ? [reply.info] : []);
182
+ }
183
+ async function queryServers(kind, dir) {
184
+ const key = readServerKey(dir);
185
+ if (key === void 0) return [];
186
+ const deadline = Date.now() + CONTROL_WAIT_MS;
187
+ const answered = [];
188
+ for (let slot = 0; slot < SERVER_SLOTS; slot++) {
189
+ let outcome = await attempt(slot, key, { kind }, 2e3, dir);
190
+ while (outcome.kind === "busy" && Date.now() < deadline) outcome = await attempt(slot, key, { kind }, 2e3, dir);
191
+ if (outcome.kind === "served") answered.push({ slot, reply: outcome.reply });
192
+ }
193
+ return answered;
194
+ }
195
+
196
+ export {
197
+ serverEnabled,
198
+ callServer,
199
+ relayViaServer,
200
+ WARM_CLI_COMMANDS,
201
+ warmCliEligible,
202
+ runCliViaServer,
203
+ serverStatuses,
204
+ queryServers
205
+ };
@@ -1,5 +1,17 @@
1
1
  import { createRequire as __cjsRequire } from 'node:module';
2
2
  const require = __cjsRequire(import.meta.url);
3
+ import {
4
+ applyExifOrientation,
5
+ calculateFitInside,
6
+ decodeBmp,
7
+ decodeGif,
8
+ decodeJpeg,
9
+ decodePng,
10
+ encodeJpeg,
11
+ encodePng,
12
+ probeBufferMeta,
13
+ resizeRgba
14
+ } from "./token-goat-chunk-RRNZMM3A.mjs";
3
15
  import {
4
16
  BODY_FIRST_TOOL_RESPONSE_KEYS,
5
17
  DELIVERS_CONTENT_RE,
@@ -18,14 +30,14 @@ import {
18
30
  replaceToolResponseField,
19
31
  stripUnsafeSuggestions,
20
32
  vscodeNativeToolInput
21
- } from "./token-goat-chunk-IZXKVT4A.mjs";
33
+ } from "./token-goat-chunk-E5TK5DNO.mjs";
22
34
  import {
23
35
  isRewriteWorthwhile,
24
36
  resolveMinNetSavingsBytes
25
- } from "./token-goat-chunk-RJH64KQH.mjs";
37
+ } from "./token-goat-chunk-ZER6EAXZ.mjs";
26
38
  import {
27
39
  foldToolName
28
- } from "./token-goat-chunk-MMLMALWK.mjs";
40
+ } from "./token-goat-chunk-EUSDXRXU.mjs";
29
41
  import {
30
42
  contentHash,
31
43
  getCompactAnySessionSync,
@@ -34,7 +46,7 @@ import {
34
46
  loadSessionCache,
35
47
  readAllSessionManifests,
36
48
  writeSessionManifest
37
- } from "./token-goat-chunk-6CCQDAYY.mjs";
49
+ } from "./token-goat-chunk-H5J3C56Q.mjs";
38
50
  import {
39
51
  exportSessionState,
40
52
  getCompactedAt,
@@ -56,10 +68,10 @@ import {
56
68
  wasFileReadThisSession,
57
69
  wasFileTruncatedThisSession,
58
70
  wasHintShown
59
- } from "./token-goat-chunk-GGLEE35R.mjs";
71
+ } from "./token-goat-chunk-TDUT2CL6.mjs";
60
72
  import {
61
73
  claudeConfigDir
62
- } from "./token-goat-chunk-MAMQPC43.mjs";
74
+ } from "./token-goat-chunk-ONXH6NZ5.mjs";
63
75
  import {
64
76
  getBashOutput,
65
77
  isGeneratedFile,
@@ -67,14 +79,14 @@ import {
67
79
  isLockFile,
68
80
  isManifestFile,
69
81
  storeBashOutputSync
70
- } from "./token-goat-chunk-HXNAC4ZF.mjs";
82
+ } from "./token-goat-chunk-O6I2XU4P.mjs";
71
83
  import {
72
84
  DEFAULT_MAX_AGE_MS,
73
85
  sweepCacheRoots
74
- } from "./token-goat-chunk-BJBRGPBX.mjs";
86
+ } from "./token-goat-chunk-D4ETHJD6.mjs";
75
87
  import {
76
88
  estimateTokens
77
- } from "./token-goat-chunk-4JMWPWCS.mjs";
89
+ } from "./token-goat-chunk-52NSDWYY.mjs";
78
90
  import {
79
91
  SOURCE_HINT,
80
92
  hasPreciseSecret,
@@ -83,7 +95,7 @@ import {
83
95
  redactSecrets,
84
96
  savedTokensFromBytes,
85
97
  summarize
86
- } from "./token-goat-chunk-MVSWBNMD.mjs";
98
+ } from "./token-goat-chunk-CIQ2FTY3.mjs";
87
99
  import {
88
100
  parse
89
101
  } from "./token-goat-chunk-3BTK54F3.mjs";
@@ -92,6 +104,7 @@ import {
92
104
  assetEmbedSha,
93
105
  deleteFileEmbeddings,
94
106
  deleteFileRows,
107
+ disabledStampCount,
95
108
  eachUnfencedLine,
96
109
  embedTexts,
97
110
  embeddingsDepsAvailable,
@@ -117,13 +130,13 @@ import {
117
130
  maxChunksEmbedSha,
118
131
  parseSourceSymbolsTreeSitterOnly,
119
132
  parserFingerprintForLanguage
120
- } from "./token-goat-chunk-D5ICEPSB.mjs";
133
+ } from "./token-goat-chunk-VMFWNHGR.mjs";
121
134
  import {
122
135
  getFileEntry,
123
136
  pathEqClause,
124
137
  projectScopeClause,
125
138
  querySymbols
126
- } from "./token-goat-chunk-HUDC5GS5.mjs";
139
+ } from "./token-goat-chunk-435UQTKD.mjs";
127
140
  import {
128
141
  detectLanguage,
129
142
  detectLanguageOfFile,
@@ -131,7 +144,7 @@ import {
131
144
  getDb,
132
145
  languageHasFlag,
133
146
  redactIfDotenv
134
- } from "./token-goat-chunk-M56BWPBN.mjs";
147
+ } from "./token-goat-chunk-7CPMDFGB.mjs";
135
148
  import {
136
149
  detectHarness,
137
150
  fileIsAbsent,
@@ -144,34 +157,32 @@ import {
144
157
  makeProjectAt,
145
158
  resolveProjectRoot,
146
159
  shortFingerprint
147
- } from "./token-goat-chunk-CC2PYJM7.mjs";
160
+ } from "./token-goat-chunk-TGOXNAHW.mjs";
148
161
  import {
149
162
  registerReset
150
- } from "./token-goat-chunk-EEIDFMEM.mjs";
163
+ } from "./token-goat-chunk-YZAAZU2S.mjs";
151
164
  import {
152
165
  IDENTICAL_READ_MIN_BODY_BYTES,
153
166
  PER_FILE_COUNTERFACTUAL_CEILING,
154
- VERSION,
155
167
  atomicWriteBytes,
156
168
  atomicWriteText,
157
169
  containsLineRun,
158
170
  countNoun,
159
- dataDir,
160
171
  decodeSource,
161
172
  ensureDirSync,
162
173
  extractErrorMessage,
163
- foldPath,
164
- globalDbPath,
165
- isNodeModulesPath,
166
174
  isTestFile,
167
175
  isUnderBlockedRoot,
168
176
  isWithinQuietHours,
169
177
  runGit,
170
178
  sanitizeIdForFilename,
171
179
  statSize,
172
- toKB,
173
- tokenGoatHome
174
- } from "./token-goat-chunk-L45ZQRT7.mjs";
180
+ toKB
181
+ } from "./token-goat-chunk-XYWPOSCN.mjs";
182
+ import {
183
+ foldPath,
184
+ isNodeModulesPath
185
+ } from "./token-goat-chunk-TCQANXYC.mjs";
175
186
  import {
176
187
  TOOL_RESULTS_ID_CHARS,
177
188
  displaySafeJson,
@@ -185,17 +196,11 @@ import {
185
196
  toDisplayPath
186
197
  } from "./token-goat-chunk-NMTKNYGF.mjs";
187
198
  import {
188
- applyExifOrientation,
189
- calculateFitInside,
190
- decodeBmp,
191
- decodeGif,
192
- decodeJpeg,
193
- decodePng,
194
- encodeJpeg,
195
- encodePng,
196
- probeBufferMeta,
197
- resizeRgba
198
- } from "./token-goat-chunk-RRNZMM3A.mjs";
199
+ VERSION,
200
+ dataDir,
201
+ globalDbPath,
202
+ tokenGoatHome
203
+ } from "./token-goat-chunk-MELOKFDJ.mjs";
199
204
  import {
200
205
  init_define_import_meta_env
201
206
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -772,8 +777,9 @@ registerHook(
772
777
  },
773
778
  { advisory: true, followsMatcher: true }
774
779
  );
775
- function categoryStats(category) {
780
+ function categoryStats(category, sessionId) {
776
781
  const db = getDb(globalDbPath());
782
+ const scope = sessionId === void 0 ? "harness = ?" : "session_id = ?";
777
783
  const row = db.prepare(
778
784
  // Three populations, deliberately not pooled. `emitted` is what was shown AND could be scored, so it is the only honest denominator for efficacy: including a row nothing could ever have satisfied would divide a real numerator by partly-imaginary rows. `unobservable` was shown but carried no pointer -- it spent bytes and earned no verdict. `detected` was never shown at all (suppressed, or declined by a net-benefit gate) and spent nothing. bytesEmitted and legacyEmissions span every row, which is correct in each case: the unobservable rows really did cost the agent, and the never-displayed ones are zero-byte, so neither distorts the spend figure. COALESCE on the counts that stay `number`: SUM over no rows is NULL where the COUNT(*) this replaced was 0, and an aggregate query always returns its row, so the `?? default` below would not have caught it.
779
785
  `SELECT COALESCE(SUM(CASE WHEN displayed = 1 AND observable = 1 THEN 1 ELSE 0 END), 0) AS emitted,
@@ -782,8 +788,8 @@ function categoryStats(category) {
782
788
  COALESCE(SUM(CASE WHEN displayed = 0 THEN 1 ELSE 0 END), 0) AS detected,
783
789
  SUM(bytes_emitted) AS bytesEmitted,
784
790
  SUM(CASE WHEN bytes_emitted IS NULL THEN 1 ELSE 0 END) AS legacyEmissions
785
- FROM hint_emissions WHERE category = ? AND harness = ?`
786
- ).get(category, getHarnessName());
791
+ FROM hint_emissions WHERE category = ? AND ${scope}`
792
+ ).get(category, sessionId ?? getHarnessName());
787
793
  return row ?? { emitted: 0, actedOn: 0, unobservable: 0, detected: 0, bytesEmitted: null, legacyEmissions: 0 };
788
794
  }
789
795
  function shouldSuppress(category, _sessionId) {
@@ -810,10 +816,10 @@ function manualMarks(category) {
810
816
  return { effective: 0, ineffective: 0 };
811
817
  }
812
818
  }
813
- function getHintStatsSummary() {
819
+ function getHintStatsSummary(sessionId) {
814
820
  const probeThresholds = loadConfig().hints.backoff_thresholds.filter((t) => t > 0);
815
821
  return HINT_CATEGORIES.map((category) => {
816
- const { emitted, actedOn, unobservable, detected, bytesEmitted, legacyEmissions } = categoryStats(category);
822
+ const { emitted, actedOn, unobservable, detected, bytesEmitted, legacyEmissions } = categoryStats(category, sessionId);
817
823
  const marks = manualMarks(category);
818
824
  const suppressed = shouldSuppress(category, "");
819
825
  return {
@@ -833,13 +839,7 @@ function getHintStatsSummary() {
833
839
  });
834
840
  }
835
841
  function getHintStatsTotals() {
836
- const db = getDb(globalDbPath());
837
- const row = db.prepare(
838
- `SELECT SUM(bytes_emitted) AS spentBytes, SUM(CASE WHEN bytes_emitted IS NULL THEN 1 ELSE 0 END) AS legacyEmissions
839
- FROM hint_emissions`
840
- ).get();
841
- const spentBytes = row?.spentBytes ?? null;
842
- const legacyEmissions = row?.legacyEmissions ?? 0;
842
+ const { spentBytes, legacyEmissions } = getHintSpendTotals();
843
843
  const savedBytes = summarize(0).by_source[SOURCE_HINT]?.bytes_saved ?? 0;
844
844
  return {
845
845
  savedBytes,
@@ -847,6 +847,14 @@ function getHintStatsTotals() {
847
847
  legacyEmissions
848
848
  };
849
849
  }
850
+ function getHintSpendTotals(sessionId) {
851
+ const db = getDb(globalDbPath());
852
+ const sql = `SELECT SUM(bytes_emitted) AS spentBytes, SUM(CASE WHEN bytes_emitted IS NULL THEN 1 ELSE 0 END) AS legacyEmissions
853
+ FROM hint_emissions`;
854
+ const stmt = db.prepare(sessionId === void 0 ? sql : `${sql} WHERE session_id = ?`);
855
+ const row = sessionId === void 0 ? stmt.get() : stmt.get(sessionId);
856
+ return { spentBytes: row?.spentBytes ?? null, legacyEmissions: row?.legacyEmissions ?? 0 };
857
+ }
850
858
  function resetHintStats() {
851
859
  const db = getDb(globalDbPath());
852
860
  db.exec("DELETE FROM hint_emissions");
@@ -2151,7 +2159,7 @@ ${dataUrl2}`);
2151
2159
  }
2152
2160
  recordStat("image_shrink", shrinkSaved, shrinkTokens, void 0, basename10);
2153
2161
  if (loadConfig().image_shrink.ocr_enabled) {
2154
- const { ocrImage, isTextHeavy, formatOcrSummary } = await import("./token-goat-chunk-7R2XYKC5.mjs");
2162
+ const { ocrImage, isTextHeavy, formatOcrSummary } = await import("./token-goat-chunk-FTP4U4QA.mjs");
2155
2163
  const ocr = await ocrImage(result.data);
2156
2164
  if (ocr !== null && isTextHeavy(ocr, loadConfig().image_shrink.ocr_min_confidence)) {
2157
2165
  const emitted = formatOcrSummary(ocr, basename10, result.originalBytes);
@@ -3664,7 +3672,8 @@ function bumpAndCheckRetry(dir, absPath) {
3664
3672
  }
3665
3673
  return true;
3666
3674
  }
3667
- function appendToDirtyQueue(dir, absPath) {
3675
+ function appendToDirtyQueue(dir, ...absPaths) {
3676
+ if (absPaths.length === 0) return true;
3668
3677
  const queuePath = dirtyQueuePathFor(dir);
3669
3678
  try {
3670
3679
  ensureDirSync(path10.dirname(queuePath));
@@ -3674,9 +3683,11 @@ function appendToDirtyQueue(dir, absPath) {
3674
3683
  if (existing.length > 0 && !existing.endsWith("\n")) leadingNewline = "\n";
3675
3684
  } catch {
3676
3685
  }
3677
- fs13.appendFileSync(queuePath, `${leadingNewline}${encodeDirtyQueueLine(absPath)}
3678
- `);
3686
+ fs13.appendFileSync(queuePath, `${leadingNewline}${absPaths.map((p) => `${encodeDirtyQueueLine(p)}
3687
+ `).join("")}`);
3688
+ return true;
3679
3689
  } catch {
3690
+ return false;
3680
3691
  }
3681
3692
  }
3682
3693
  function requeueDirtyPath(dir, absPath) {
@@ -3975,6 +3986,32 @@ var WorkerAlreadyRunningError = class extends Error {
3975
3986
  this.name = "WorkerAlreadyRunningError";
3976
3987
  }
3977
3988
  };
3989
+ var WorkerDataDirUnwritableError = class extends Error {
3990
+ constructor(dir, cause) {
3991
+ super(`the data directory ${displaySafeText(dir)} cannot be written (${extractErrorMessage(cause)}), and the worker keeps its pid file, queue and index there; make it writable and run \`token-goat worker start\` again`, { cause });
3992
+ this.name = "WorkerDataDirUnwritableError";
3993
+ }
3994
+ };
3995
+ function dataDirWriteRefusal(dir) {
3996
+ const probe = path10.join(dir, `.write-probe-${process.pid}`);
3997
+ try {
3998
+ fs13.writeFileSync(probe, "");
3999
+ } catch (e) {
4000
+ return e;
4001
+ }
4002
+ try {
4003
+ fs13.rmSync(probe, { force: true });
4004
+ } catch {
4005
+ }
4006
+ return void 0;
4007
+ }
4008
+ function discardSpawnedWorker(child, pid) {
4009
+ try {
4010
+ process.kill(pid);
4011
+ } catch {
4012
+ }
4013
+ child.unref();
4014
+ }
3978
4015
  function claimWorkerPidFile(dir, pid) {
3979
4016
  const pidPath = workerPidPath(dir);
3980
4017
  try {
@@ -4054,6 +4091,8 @@ function startDetachedWorker(opts) {
4054
4091
  } catch (e) {
4055
4092
  if (e.code !== "EEXIST" || !fs13.existsSync(dir)) throw e;
4056
4093
  }
4094
+ const refusal = dataDirWriteRefusal(dir);
4095
+ if (refusal !== void 0) throw new WorkerDataDirUnwritableError(dir, refusal);
4057
4096
  const child = spawn(
4058
4097
  process.execPath,
4059
4098
  [daemonEntryScript(), "--worker-daemon"],
@@ -4072,12 +4111,15 @@ function startDetachedWorker(opts) {
4072
4111
  if (pid === void 0) {
4073
4112
  throw new Error("startDetachedWorker: spawn produced no pid");
4074
4113
  }
4075
- if (!claimWorkerPidFile(dir, pid)) {
4076
- try {
4077
- process.kill(pid);
4078
- } catch {
4079
- }
4080
- child.unref();
4114
+ let claimed;
4115
+ try {
4116
+ claimed = claimWorkerPidFile(dir, pid);
4117
+ } catch (e) {
4118
+ discardSpawnedWorker(child, pid);
4119
+ throw e;
4120
+ }
4121
+ if (!claimed) {
4122
+ discardSpawnedWorker(child, pid);
4081
4123
  throw new WorkerAlreadyRunningError();
4082
4124
  }
4083
4125
  try {
@@ -4090,12 +4132,39 @@ function startDetachedWorker(opts) {
4090
4132
  var KNOWN_ROOTS_SWEEP_INTERVAL_MS = 24 * 60 * 60 * 1e3;
4091
4133
  var IDLE_VACUUM_INTERVAL_MS = 6 * 60 * 60 * 1e3;
4092
4134
  var IDLE_VACUUM_COOLDOWN_MS = 5 * 60 * 1e3;
4135
+ var EMBED_BACKLOG_BATCH = 50;
4136
+ var EMBED_BACKLOG_SCAN = 1e3;
4137
+ function requeueStaleEmbeddings(dir, cursor) {
4138
+ const indexing = loadConfig().indexing;
4139
+ const db = getDb(path10.join(dir, "global.db"));
4140
+ const symbolOnlyKb = indexing?.large_file_symbol_only_kb ?? 0;
4141
+ const maxChunks = indexing?.max_chunks_per_file ?? 0;
4142
+ const rows = db.prepare("SELECT path, sha, embed_sha FROM files WHERE path > ? ORDER BY path LIMIT ?").all(cursor, EMBED_BACKLOG_SCAN);
4143
+ const owed = [];
4144
+ let resumeAfter = null;
4145
+ for (const row of rows) {
4146
+ resumeAfter = row.path;
4147
+ if (isUnderSystemTemp(row.path) || isEmbedFresh(row.embed_sha ?? void 0, row.sha, true, true, symbolOnlyKb, maxChunks)) continue;
4148
+ if (fileIsAbsent(row.path)) continue;
4149
+ owed.push(row.path);
4150
+ if (owed.length === EMBED_BACKLOG_BATCH) break;
4151
+ }
4152
+ if (!appendToDirtyQueue(dir, ...owed)) return cursor;
4153
+ return owed.length === EMBED_BACKLOG_BATCH || rows.length === EMBED_BACKLOG_SCAN ? resumeAfter : null;
4154
+ }
4155
+ function embeddingsReady(dir) {
4156
+ const dbPath = path10.join(dir, "global.db");
4157
+ return fs13.existsSync(dbPath) && loadConfig().indexing?.embeddings_enabled !== false && embeddingsDepsAvailable(getDb(dbPath));
4158
+ }
4093
4159
  async function runWorkerLoop(dir, pollIntervalMs, shouldStop = () => false) {
4094
4160
  await loadRegexExtractors();
4095
4161
  let lastSnapshotCleanupMs = 0;
4096
4162
  let lastKnownRootsSweepMs = 0;
4097
4163
  let lastIdleVacuumMs = 0;
4098
4164
  let lastActiveMs = Date.now();
4165
+ let embedBacklogCursor = "";
4166
+ let embeddingsWereReady = true;
4167
+ let disabledStampsSeen = disabledStampCount();
4099
4168
  let ownedPidFile = false;
4100
4169
  while (!shouldStop()) {
4101
4170
  if (!fs13.existsSync(dir)) break;
@@ -4109,6 +4178,16 @@ async function runWorkerLoop(dir, pollIntervalMs, shouldStop = () => false) {
4109
4178
  }
4110
4179
  if (processed > 0) {
4111
4180
  lastActiveMs = Date.now();
4181
+ } else if (inFlightEmbeddings.size === 0) {
4182
+ try {
4183
+ const ready = embeddingsReady(dir);
4184
+ const stamps = disabledStampCount();
4185
+ if (ready && (!embeddingsWereReady || stamps !== disabledStampsSeen)) embedBacklogCursor = "";
4186
+ embeddingsWereReady = ready;
4187
+ if (ready) disabledStampsSeen = stamps;
4188
+ if (ready && embedBacklogCursor !== null) embedBacklogCursor = requeueStaleEmbeddings(dir, embedBacklogCursor);
4189
+ } catch {
4190
+ }
4112
4191
  }
4113
4192
  if (Date.now() - lastSnapshotCleanupMs >= SNAPSHOT_CLEANUP_INTERVAL_MS) {
4114
4193
  try {
@@ -4220,7 +4299,18 @@ function appendDirtyPaths(normalizedPaths) {
4220
4299
  }
4221
4300
  const body = normalizedPaths.map((p) => `${encodeDirtyQueueLine(p)}
4222
4301
  `).join("");
4223
- fs14.appendFileSync(queuePath, `${dirtyQueueLeadingNewline(queuePath)}${body}`);
4302
+ for (let attempt = 0; attempt < 3; attempt++) {
4303
+ if (appendToLiveQueue(queuePath, `${dirtyQueueLeadingNewline(queuePath)}${body}`)) return;
4304
+ }
4305
+ }
4306
+ function appendToLiveQueue(queuePath, data) {
4307
+ const fd = fs14.openSync(queuePath, "a");
4308
+ try {
4309
+ fs14.writeFileSync(fd, data);
4310
+ return fs14.statSync(queuePath, { bigint: true, throwIfNoEntry: false })?.ino === fs14.fstatSync(fd, { bigint: true }).ino;
4311
+ } finally {
4312
+ fs14.closeSync(fd);
4313
+ }
4224
4314
  }
4225
4315
  function appendDirtyPath(normalizedPath) {
4226
4316
  appendDirtyPaths([normalizedPath]);
@@ -4573,6 +4663,14 @@ function isSessionArtifactFile(filePath) {
4573
4663
  if (new RegExp("[/\\\\]tool-results[/\\\\]" + TOOL_RESULTS_ID_CHARS + "\\.txt$", "i").test(filePath)) return true;
4574
4664
  return false;
4575
4665
  }
4666
+ function lineWindowBytes(filePath, offset, limit) {
4667
+ try {
4668
+ const lines = fs15.readFileSync(filePath, "utf-8").split("\n").slice(offset - 1, offset - 1 + limit);
4669
+ return lines.reduce((sum, line) => sum + Buffer.byteLength(line, "utf-8") + 1, 0);
4670
+ } catch {
4671
+ return Infinity;
4672
+ }
4673
+ }
4576
4674
  function sessionArtifactRecall(rawPath) {
4577
4675
  const filePath = displaySafePath(rawPath);
4578
4676
  return 'Use `token-goat bash-output --file "' + filePath + '" --tail 50` (or `--grep PATTERN`) to read a slice instead of the full file.';
@@ -5110,14 +5208,17 @@ function preReadHandlerInner(event) {
5110
5208
  const isTaskOutput = /[/\\]tasks[/\\][a-z0-9]+\.output$/i.test(normalized);
5111
5209
  const label = isTaskOutput ? "Session transcript" : "Tool-result file";
5112
5210
  const outputSize = statSize(normalized);
5113
- recordActualRead(event, normalized);
5114
- if (outputSize !== null && outputSize >= TASK_OUTPUT_DENY_BYTES) {
5211
+ const window = readRequestedSliceWindow(event);
5212
+ const windowBytes = window.limit === void 0 ? void 0 : lineWindowBytes(normalized, window.offset ?? 1, window.limit);
5213
+ if (outputSize !== null && outputSize >= TASK_OUTPUT_DENY_BYTES && (windowBytes === void 0 || windowBytes >= TASK_OUTPUT_DENY_BYTES)) {
5115
5214
  const artifactDenyCredit = counterfactualCredit(outputSize);
5116
5215
  recordStat("session_hint", artifactDenyCredit, savedTokensFromBytes(artifactDenyCredit), void 0, "artifact-large-deny");
5216
+ const windowNote = windowBytes === void 0 || window.limit === void 0 || !Number.isFinite(windowBytes) ? "" : " Lines " + (window.offset ?? 1) + "-" + ((window.offset ?? 1) + window.limit - 1) + " span " + toKB(windowBytes) + "KB.";
5117
5217
  return denyOutput(
5118
- label + " is large (" + toKB(outputSize) + "KB). " + sessionArtifactRecall(normalized)
5218
+ label + " is large (" + toKB(outputSize) + "KB)." + windowNote + " " + sessionArtifactRecall(normalized) + " A Read with `offset` and `limit` spanning under " + toKB(TASK_OUTPUT_DENY_BYTES) + "KB goes through."
5119
5219
  );
5120
5220
  }
5221
+ recordActualRead(event, normalized);
5121
5222
  return quietContextOutput(label + ": " + sessionArtifactRecall(normalized));
5122
5223
  }
5123
5224
  }
@@ -6910,6 +7011,7 @@ export {
6910
7011
  meetsSavingsFloor,
6911
7012
  getHintStatsSummary,
6912
7013
  getHintStatsTotals,
7014
+ getHintSpendTotals,
6913
7015
  resetHintStats,
6914
7016
  markCategoryEffective,
6915
7017
  markCategoryIneffective,
@@ -6922,7 +7024,9 @@ export {
6922
7024
  servedRunNotice,
6923
7025
  planServedElisions,
6924
7026
  LARGE_SYMBOL_LINE_THRESHOLD,
7027
+ SLICE_ESTIMATE_SCAN_CAP_BYTES,
6925
7028
  buildLineDiff,
7029
+ countTextLines,
6926
7030
  visionTokens,
6927
7031
  visionTokensSaved,
6928
7032
  visionTokensSavedByText,
@@ -6963,6 +7067,7 @@ export {
6963
7067
  ensureWorkerAlive,
6964
7068
  stopWorker,
6965
7069
  WorkerAlreadyRunningError,
7070
+ dataDirWriteRefusal,
6966
7071
  startDetachedWorker,
6967
7072
  runDetachedWorkerDaemon,
6968
7073
  appendDirtyPath,