token-goat 2.9.29 → 2.9.31
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 +53 -42
- package/SECURITY.md +37 -11
- package/THIRD_PARTY_NOTICES.md +41 -4
- package/dist/native/linux-arm64/tg-hook +0 -0
- package/dist/native/linux-x64/tg-hook +0 -0
- package/dist/native/win32-arm64/tg-hook.exe +0 -0
- package/dist/native/win32-x64/tg-hook.exe +0 -0
- package/dist/ort-wasm-simd-threaded.mjs +59 -0
- package/dist/{token-goat-chunk-SE6E4BKJ.mjs → token-goat-chunk-25TRAWET.mjs} +23 -6
- package/dist/token-goat-chunk-2KXO6V2B.mjs +203 -0
- package/dist/{token-goat-chunk-UXSXQQIY.mjs → token-goat-chunk-2M7E4PF7.mjs} +43 -14
- package/dist/token-goat-chunk-2UPZGKKY.mjs +188 -0
- package/dist/token-goat-chunk-2WLPWKHV.mjs +135 -0
- package/dist/token-goat-chunk-2XBMMDBD.mjs +126 -0
- package/dist/token-goat-chunk-32ZOY4N5.mjs +23 -0
- package/dist/token-goat-chunk-3EZRNKTK.mjs +188 -0
- package/dist/token-goat-chunk-4ADZHI7J.mjs +63 -0
- package/dist/token-goat-chunk-4GBVPH3D.mjs +242 -0
- package/dist/{token-goat-chunk-2WOUYWLM.mjs → token-goat-chunk-4GILLLWY.mjs} +34 -7
- package/dist/token-goat-chunk-4NAPX7BA.mjs +90 -0
- package/dist/{token-goat-chunk-NMBWLRHW.mjs → token-goat-chunk-4SC7UJYV.mjs} +9981 -11563
- package/dist/token-goat-chunk-4SMRO4TO.mjs +366 -0
- package/dist/{token-goat-chunk-O6I2XU4P.mjs → token-goat-chunk-4ZBFWLXF.mjs} +310 -441
- package/dist/token-goat-chunk-57BIAXJL.mjs +286 -0
- package/dist/token-goat-chunk-5AC66HNP.mjs +115 -0
- package/dist/token-goat-chunk-5IMLKSOP.mjs +145 -0
- package/dist/token-goat-chunk-5RG5SBL6.mjs +221 -0
- package/dist/{token-goat-chunk-RRNZMM3A.mjs → token-goat-chunk-5Y6ZYL6U.mjs} +21 -2
- package/dist/token-goat-chunk-646E6U44.mjs +398 -0
- package/dist/token-goat-chunk-65N4RHP4.mjs +33 -0
- package/dist/{token-goat-chunk-6AK46ZT7.mjs → token-goat-chunk-6DG6HWP3.mjs} +13 -3
- package/dist/token-goat-chunk-6ENQSNRZ.mjs +573 -0
- package/dist/token-goat-chunk-6ZY4GNF2.mjs +91 -0
- package/dist/{token-goat-chunk-E5TK5DNO.mjs → token-goat-chunk-76FGDLRO.mjs} +574 -340
- package/dist/{token-goat-chunk-TGOXNAHW.mjs → token-goat-chunk-7EZTZOMC.mjs} +780 -767
- package/dist/token-goat-chunk-7MAOA6X4.mjs +3647 -0
- package/dist/token-goat-chunk-7R2ZVVAX.mjs +218 -0
- package/dist/{token-goat-chunk-TCQANXYC.mjs → token-goat-chunk-AM5V6GSX.mjs} +18 -2
- package/dist/token-goat-chunk-AUNGYYQX.mjs +184 -0
- package/dist/token-goat-chunk-AUQYRMMH.mjs +2985 -0
- package/dist/token-goat-chunk-B3PEKBYG.mjs +128 -0
- package/dist/{token-goat-chunk-KOPIR3KZ.mjs → token-goat-chunk-BA4HI6BW.mjs} +1910 -165
- package/dist/{token-goat-chunk-52NSDWYY.mjs → token-goat-chunk-BFCWY73P.mjs} +58 -20
- package/dist/token-goat-chunk-BPGCUMR7.mjs +30 -0
- package/dist/token-goat-chunk-BWGFUZZE.mjs +25 -0
- package/dist/token-goat-chunk-C75NA7PL.mjs +322 -0
- package/dist/token-goat-chunk-CBIQ7WTD.mjs +87 -0
- package/dist/token-goat-chunk-CETM74KC.mjs +307 -0
- package/dist/token-goat-chunk-CIMQ2BB3.mjs +233 -0
- package/dist/{token-goat-chunk-DNSPXQXQ.mjs → token-goat-chunk-CJLS3CDL.mjs} +70 -18
- package/dist/{token-goat-chunk-MELOKFDJ.mjs → token-goat-chunk-CO3UYX6G.mjs} +7 -1
- package/dist/token-goat-chunk-COPNXRJM.mjs +154 -0
- package/dist/token-goat-chunk-CSJ5L3NL.mjs +479 -0
- package/dist/token-goat-chunk-CVCEVUGK.mjs +315 -0
- package/dist/token-goat-chunk-CXHOFN7R.mjs +371 -0
- package/dist/token-goat-chunk-D735C4QM.mjs +603 -0
- package/dist/{token-goat-chunk-E4ZOJIZK.mjs → token-goat-chunk-DGS2LVNA.mjs} +70 -160
- package/dist/{token-goat-chunk-L7H3U27L.mjs → token-goat-chunk-DOWRSMWO.mjs} +1 -1
- package/dist/token-goat-chunk-E45INMY3.mjs +71 -0
- package/dist/token-goat-chunk-EC5F37F4.mjs +244 -0
- package/dist/{token-goat-chunk-XTQAOTSO.mjs → token-goat-chunk-EDBDRVH5.mjs} +4 -1
- package/dist/token-goat-chunk-EELTBKDM.mjs +613 -0
- package/dist/token-goat-chunk-EVMZJ27Z.mjs +147 -0
- package/dist/token-goat-chunk-EXKGNHEG.mjs +2096 -0
- package/dist/{token-goat-chunk-YOOVFPTP.mjs → token-goat-chunk-F4HYL64R.mjs} +12 -2
- package/dist/token-goat-chunk-F6PAUIEK.mjs +624 -0
- package/dist/token-goat-chunk-FDSREWLX.mjs +692 -0
- package/dist/{token-goat-chunk-NMTKNYGF.mjs → token-goat-chunk-FNFBKLRD.mjs} +74 -9
- package/dist/token-goat-chunk-G5PJ7AGM.mjs +36 -0
- package/dist/token-goat-chunk-GGGG7RWB.mjs +236 -0
- package/dist/{token-goat-chunk-TDUT2CL6.mjs → token-goat-chunk-GL3ETKSC.mjs} +276 -19
- package/dist/{token-goat-chunk-7CPMDFGB.mjs → token-goat-chunk-GVB2MUST.mjs} +265 -1567
- package/dist/token-goat-chunk-GWFLAUMQ.mjs +307 -0
- package/dist/token-goat-chunk-HAVAOB3S.mjs +87 -0
- package/dist/token-goat-chunk-HLPW63A7.mjs +48 -0
- package/dist/token-goat-chunk-HU4TORC5.mjs +1377 -0
- package/dist/token-goat-chunk-I7VKZZAW.mjs +35 -0
- package/dist/token-goat-chunk-IA6XSPE3.mjs +218 -0
- package/dist/token-goat-chunk-IAGXMHIK.mjs +863 -0
- package/dist/{token-goat-chunk-435UQTKD.mjs → token-goat-chunk-IK2DRMFX.mjs} +129 -74
- package/dist/{token-goat-chunk-ZER6EAXZ.mjs → token-goat-chunk-INNPTRUX.mjs} +2954 -2783
- package/dist/token-goat-chunk-JJ5BX4F4.mjs +129 -0
- package/dist/token-goat-chunk-JVFSHVFJ.mjs +129 -0
- package/dist/token-goat-chunk-KGEFFSHD.mjs +50 -0
- package/dist/token-goat-chunk-KKUFXAPD.mjs +25 -0
- package/dist/token-goat-chunk-KQBLRPBN.mjs +433 -0
- package/dist/token-goat-chunk-LCNQ2CNN.mjs +497 -0
- package/dist/token-goat-chunk-M3LFJDPU.mjs +58 -0
- package/dist/token-goat-chunk-M52KPT3C.mjs +87 -0
- package/dist/token-goat-chunk-MBEG42H7.mjs +150 -0
- package/dist/{token-goat-chunk-EVC4TOLE.mjs → token-goat-chunk-METECDOH.mjs} +3 -12
- package/dist/{token-goat-chunk-2AWQ2R5X.mjs → token-goat-chunk-MHX7XCC3.mjs} +3 -2
- package/dist/token-goat-chunk-MNWKPRAL.mjs +13 -0
- package/dist/token-goat-chunk-N5LSOVSU.mjs +137 -0
- package/dist/{token-goat-chunk-DPNLUJWB.mjs → token-goat-chunk-N5MMR2IW.mjs} +30 -8
- package/dist/token-goat-chunk-N7B3JQ2C.mjs +160 -0
- package/dist/{token-goat-chunk-VMFWNHGR.mjs → token-goat-chunk-NISNMD7T.mjs} +2545 -2953
- package/dist/token-goat-chunk-NMD42SFQ.mjs +434 -0
- package/dist/token-goat-chunk-NOSS5VWY.mjs +174 -0
- package/dist/token-goat-chunk-NSNSPPBG.mjs +69 -0
- package/dist/token-goat-chunk-OBOFIHKN.mjs +38 -0
- package/dist/token-goat-chunk-OBRFJ5O5.mjs +76 -0
- package/dist/token-goat-chunk-ODBT2USM.mjs +800 -0
- package/dist/token-goat-chunk-OS5EM5PP.mjs +107 -0
- package/dist/token-goat-chunk-OUKDTVNU.mjs +1178 -0
- package/dist/token-goat-chunk-OXFMP75N.mjs +566 -0
- package/dist/{token-goat-chunk-ASLWOQ3I.mjs → token-goat-chunk-OYIYKDDT.mjs} +2 -1
- package/dist/{token-goat-chunk-67BNIKKO.mjs → token-goat-chunk-P6HQSWQ3.mjs} +55 -47
- package/dist/token-goat-chunk-P6VGNTQT.mjs +71 -0
- package/dist/token-goat-chunk-PFWIMH2E.mjs +261 -0
- package/dist/token-goat-chunk-PJZXIS3G.mjs +39 -0
- package/dist/token-goat-chunk-PUO5INXP.mjs +606 -0
- package/dist/token-goat-chunk-PX5PQWTY.mjs +462 -0
- package/dist/token-goat-chunk-Q5QDBC6O.mjs +111 -0
- package/dist/token-goat-chunk-QFNQXSDT.mjs +40 -0
- package/dist/token-goat-chunk-QH7YVYOY.mjs +3957 -0
- package/dist/token-goat-chunk-QLMUHEPB.mjs +43 -0
- package/dist/{token-goat-chunk-PYSUADX4.mjs → token-goat-chunk-QQOJIHL3.mjs} +50 -14
- package/dist/token-goat-chunk-QQTWJY2O.mjs +85 -0
- package/dist/token-goat-chunk-QYHO5CPH.mjs +93 -0
- package/dist/token-goat-chunk-RELAVWAD.mjs +27 -0
- package/dist/token-goat-chunk-RSLPOBKQ.mjs +339 -0
- package/dist/token-goat-chunk-SAMFDIS2.mjs +712 -0
- package/dist/token-goat-chunk-SDELXLDM.mjs +48 -0
- package/dist/{token-goat-chunk-PGTH2U4C.mjs → token-goat-chunk-SOAFZNNZ.mjs} +164 -40
- package/dist/{token-goat-chunk-G23DWHV4.mjs → token-goat-chunk-SRTHT7KV.mjs} +33 -15
- package/dist/token-goat-chunk-T5P5ACNQ.mjs +212 -0
- package/dist/token-goat-chunk-T5YGG4V3.mjs +45 -0
- package/dist/token-goat-chunk-TAUZ4OFS.mjs +110 -0
- package/dist/token-goat-chunk-TM6MC754.mjs +40 -0
- package/dist/token-goat-chunk-TWUKBOMP.mjs +72 -0
- package/dist/token-goat-chunk-U2KSB4SG.mjs +56 -0
- package/dist/token-goat-chunk-U4WHMG6Y.mjs +898 -0
- package/dist/token-goat-chunk-UA5V6P3P.mjs +122 -0
- package/dist/token-goat-chunk-UGJHGR5A.mjs +52 -0
- package/dist/{token-goat-chunk-RQGGMPCR.mjs → token-goat-chunk-UOUDVA5U.mjs} +76 -16
- package/dist/{token-goat-chunk-HNFZZHFW.mjs → token-goat-chunk-URRJ33GR.mjs} +22 -4
- package/dist/token-goat-chunk-UZOROKIS.mjs +165 -0
- package/dist/token-goat-chunk-VIHGGGEI.mjs +4234 -0
- package/dist/token-goat-chunk-VTJLAA7P.mjs +21 -0
- package/dist/token-goat-chunk-VWDXLT4F.mjs +678 -0
- package/dist/token-goat-chunk-VWZA2H4P.mjs +368 -0
- package/dist/{token-goat-chunk-QO3LXVVR.mjs → token-goat-chunk-VXEXMJDL.mjs} +2964 -3153
- package/dist/token-goat-chunk-WBA5SKT4.mjs +547 -0
- package/dist/{token-goat-chunk-ONXH6NZ5.mjs → token-goat-chunk-WDH44VAU.mjs} +19 -22
- package/dist/token-goat-chunk-X2SUP3EI.mjs +107 -0
- package/dist/token-goat-chunk-X3BELZSJ.mjs +125 -0
- package/dist/{token-goat-chunk-RLP6J7WR.mjs → token-goat-chunk-XLRBNZCC.mjs} +40 -21
- package/dist/{token-goat-chunk-S4VSXURL.mjs → token-goat-chunk-XRKUX6CM.mjs} +4 -0
- package/dist/token-goat-chunk-XX6O25RN.mjs +82 -0
- package/dist/token-goat-chunk-XZSUHBVS.mjs +65 -0
- package/dist/token-goat-chunk-Y2ZTQOCL.mjs +35 -0
- package/dist/{token-goat-chunk-UA5BKWWQ.mjs → token-goat-chunk-YB4VMGK2.mjs} +15 -4
- package/dist/token-goat-chunk-YBIIY3HR.mjs +51 -0
- package/dist/{token-goat-chunk-PKRWMHVP.mjs → token-goat-chunk-YHVDKQBR.mjs} +389 -221
- package/dist/token-goat-chunk-YJB5XLWI.mjs +26 -0
- package/dist/{token-goat-chunk-PQ53BSCF.mjs → token-goat-chunk-YKB6AQG3.mjs} +53 -31
- package/dist/token-goat-chunk-YMTG2YA5.mjs +35 -0
- package/dist/token-goat-chunk-YPBZYQRV.mjs +40 -0
- package/dist/{token-goat-chunk-HUYUHODZ.mjs → token-goat-chunk-YY6AVUFL.mjs} +13246 -12247
- package/dist/token-goat-chunk-Z7N5OMMP.mjs +98 -0
- package/dist/{token-goat-chunk-BGHSSJUA.mjs → token-goat-chunk-ZFOBKUWH.mjs} +1 -1
- package/dist/token-goat-chunk-ZMBL6UVV.mjs +110 -0
- package/dist/token-goat-chunk-ZNMNUPAZ.mjs +938 -0
- package/dist/token-goat-hook-client.cjs +87 -23
- package/dist/token-goat-hook-client.mjs +3 -3
- package/dist/token-goat-hook.mjs +76 -31
- package/dist/token-goat.core.mjs +6 -6
- package/docs/C4_RUNTIME_ARCHITECTURE.md +2 -2
- package/docs/cli.md +113 -60
- package/docs/install.md +63 -20
- package/docs/security.md +10 -8
- package/package.json +18 -7
- package/scripts/verify-native-dist.mjs +386 -0
- package/dist/token-goat-chunk-2NNUA2LR.mjs +0 -143
- package/dist/token-goat-chunk-44BM7DDQ.mjs +0 -294
- package/dist/token-goat-chunk-BGYOZ6DO.mjs +0 -24
- package/dist/token-goat-chunk-C5YPNZKQ.mjs +0 -318
- package/dist/token-goat-chunk-CIQ2FTY3.mjs +0 -1990
- package/dist/token-goat-chunk-D4ETHJD6.mjs +0 -246
- package/dist/token-goat-chunk-DNRPXHYH.mjs +0 -1062
- package/dist/token-goat-chunk-EUSDXRXU.mjs +0 -1429
- package/dist/token-goat-chunk-FTP4U4QA.mjs +0 -64
- package/dist/token-goat-chunk-G7IWXCFF.mjs +0 -456
- package/dist/token-goat-chunk-GLXRTTLE.mjs +0 -36
- package/dist/token-goat-chunk-H5J3C56Q.mjs +0 -1511
- package/dist/token-goat-chunk-IVWI2OCK.mjs +0 -368
- package/dist/token-goat-chunk-JTKCQMQA.mjs +0 -418
- package/dist/token-goat-chunk-LZNBQTDK.mjs +0 -26
- package/dist/token-goat-chunk-ORNFMIER.mjs +0 -295
- package/dist/token-goat-chunk-RTMVLHWX.mjs +0 -7113
- package/dist/token-goat-chunk-VQ6F6T7X.mjs +0 -36
- package/dist/token-goat-chunk-VZQEWRVH.mjs +0 -312
- package/dist/token-goat-chunk-XYWPOSCN.mjs +0 -807
- package/dist/token-goat-chunk-YAGLESS3.mjs +0 -23
- package/dist/token-goat-chunk-YKSRAWUU.mjs +0 -33
- package/dist/token-goat-chunk-Z6KBMOBI.mjs +0 -53
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createRequire as __cjsRequire } from 'node:module';
|
|
2
|
+
const require = __cjsRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
init_define_import_meta_env
|
|
5
|
+
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
6
|
+
|
|
7
|
+
// src/windows_powershell.ts
|
|
8
|
+
init_define_import_meta_env();
|
|
9
|
+
|
|
10
|
+
// src/windows_system32.ts
|
|
11
|
+
init_define_import_meta_env();
|
|
12
|
+
import * as fs from "node:fs";
|
|
13
|
+
import * as path from "node:path";
|
|
14
|
+
var DEFAULT_WINDOWS_DIR = "C:\\Windows";
|
|
15
|
+
function windowsSystem32Exe(...rel) {
|
|
16
|
+
const missing = path.join(DEFAULT_WINDOWS_DIR, "System32", ...rel);
|
|
17
|
+
for (const root of [process.env["SystemRoot"], process.env["windir"], DEFAULT_WINDOWS_DIR]) {
|
|
18
|
+
if (root === void 0 || !path.win32.isAbsolute(root)) continue;
|
|
19
|
+
const exe = path.join(root, "System32", ...rel);
|
|
20
|
+
if (fs.existsSync(exe)) return exe;
|
|
21
|
+
}
|
|
22
|
+
return missing;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/windows_powershell.ts
|
|
26
|
+
function windowsPowerShellPath() {
|
|
27
|
+
return windowsSystem32Exe("WindowsPowerShell", "v1.0", "powershell.exe");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
windowsSystem32Exe,
|
|
32
|
+
windowsPowerShellPath
|
|
33
|
+
};
|
|
@@ -3,6 +3,12 @@ const require = __cjsRequire(import.meta.url);
|
|
|
3
3
|
import {
|
|
4
4
|
external_exports
|
|
5
5
|
} from "./token-goat-chunk-3U6ZYVX5.mjs";
|
|
6
|
+
import {
|
|
7
|
+
answeringMcpToolCall
|
|
8
|
+
} from "./token-goat-chunk-KGEFFSHD.mjs";
|
|
9
|
+
import {
|
|
10
|
+
displaySafeText
|
|
11
|
+
} from "./token-goat-chunk-FNFBKLRD.mjs";
|
|
6
12
|
import {
|
|
7
13
|
init_define_import_meta_env
|
|
8
14
|
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
@@ -91,6 +97,10 @@ var McpServer = class {
|
|
|
91
97
|
}
|
|
92
98
|
}
|
|
93
99
|
async handleMessage(message) {
|
|
100
|
+
if (message === null || typeof message !== "object" || Array.isArray(message)) {
|
|
101
|
+
await this.sendError(void 0, JSONRPC_INVALID_REQUEST, "Invalid Request: a JSON-RPC message must be a JSON object");
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
94
104
|
if (!isRequest(message)) return;
|
|
95
105
|
const { id, method } = message;
|
|
96
106
|
const params = message.params ?? {};
|
|
@@ -109,7 +119,7 @@ var McpServer = class {
|
|
|
109
119
|
await this.send({ jsonrpc: "2.0", id, result: await this.callTool(params) });
|
|
110
120
|
return;
|
|
111
121
|
default:
|
|
112
|
-
await this.sendError(id, JSONRPC_METHOD_NOT_FOUND, `Method not found: ${method}`);
|
|
122
|
+
await this.sendError(id, JSONRPC_METHOD_NOT_FOUND, `Method not found: ${displaySafeText(method)}`);
|
|
113
123
|
return;
|
|
114
124
|
}
|
|
115
125
|
} catch (err) {
|
|
@@ -117,7 +127,7 @@ var McpServer = class {
|
|
|
117
127
|
}
|
|
118
128
|
}
|
|
119
129
|
async sendError(id, code, message) {
|
|
120
|
-
await this.send({ jsonrpc: "2.0", id, error: { code, message } });
|
|
130
|
+
await this.send(id === void 0 ? { jsonrpc: "2.0", error: { code, message } } : { jsonrpc: "2.0", id, error: { code, message } });
|
|
121
131
|
}
|
|
122
132
|
initializeResult(params) {
|
|
123
133
|
const requested = params["protocolVersion"];
|
|
@@ -153,7 +163,7 @@ var McpServer = class {
|
|
|
153
163
|
);
|
|
154
164
|
}
|
|
155
165
|
try {
|
|
156
|
-
return await handler(parsed.data);
|
|
166
|
+
return await answeringMcpToolCall(() => handler(parsed.data), new Set(this.tools.keys()));
|
|
157
167
|
} catch (err) {
|
|
158
168
|
return errorText(err instanceof Error ? err.message : String(err));
|
|
159
169
|
}
|
|
@@ -0,0 +1,573 @@
|
|
|
1
|
+
import { createRequire as __cjsRequire } from 'node:module';
|
|
2
|
+
const require = __cjsRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
diagnoseSqlFailure
|
|
5
|
+
} from "./token-goat-chunk-PX5PQWTY.mjs";
|
|
6
|
+
import {
|
|
7
|
+
SEARCH_COMMAND_RE,
|
|
8
|
+
classifyToolError
|
|
9
|
+
} from "./token-goat-chunk-JVFSHVFJ.mjs";
|
|
10
|
+
import {
|
|
11
|
+
PIPELINE_PASSTHROUGH_HEADS,
|
|
12
|
+
extractCommand,
|
|
13
|
+
pureFileReadPath,
|
|
14
|
+
stripCommandPrefix,
|
|
15
|
+
unwrapCompressCommand
|
|
16
|
+
} from "./token-goat-chunk-ODBT2USM.mjs";
|
|
17
|
+
import {
|
|
18
|
+
splitShellSegments,
|
|
19
|
+
stripLeadingAssignments
|
|
20
|
+
} from "./token-goat-chunk-DGS2LVNA.mjs";
|
|
21
|
+
import {
|
|
22
|
+
applyHintTracking,
|
|
23
|
+
settleSelfScoredHints,
|
|
24
|
+
uncorrelatedHint
|
|
25
|
+
} from "./token-goat-chunk-4SMRO4TO.mjs";
|
|
26
|
+
import {
|
|
27
|
+
sessionSidecarPath
|
|
28
|
+
} from "./token-goat-chunk-WBA5SKT4.mjs";
|
|
29
|
+
import {
|
|
30
|
+
registerHook,
|
|
31
|
+
sessionStateKey
|
|
32
|
+
} from "./token-goat-chunk-C75NA7PL.mjs";
|
|
33
|
+
import {
|
|
34
|
+
OUTPUT_FIRST_TOOL_RESPONSE_KEYS,
|
|
35
|
+
contextOutput,
|
|
36
|
+
estimateResultCount,
|
|
37
|
+
extractToolResponseField,
|
|
38
|
+
getFilePath,
|
|
39
|
+
getToolInput,
|
|
40
|
+
getToolName,
|
|
41
|
+
passOutput,
|
|
42
|
+
resolveEventPath,
|
|
43
|
+
structuredResultCount
|
|
44
|
+
} from "./token-goat-chunk-76FGDLRO.mjs";
|
|
45
|
+
import {
|
|
46
|
+
recordStat
|
|
47
|
+
} from "./token-goat-chunk-U4WHMG6Y.mjs";
|
|
48
|
+
import {
|
|
49
|
+
buildLineIndex,
|
|
50
|
+
offsetToLine
|
|
51
|
+
} from "./token-goat-chunk-OUKDTVNU.mjs";
|
|
52
|
+
import {
|
|
53
|
+
redactSecrets
|
|
54
|
+
} from "./token-goat-chunk-T5P5ACNQ.mjs";
|
|
55
|
+
import {
|
|
56
|
+
ensureDirSync
|
|
57
|
+
} from "./token-goat-chunk-HU4TORC5.mjs";
|
|
58
|
+
import {
|
|
59
|
+
displaySafeText,
|
|
60
|
+
hostPathOfIndexKey,
|
|
61
|
+
normalizePath
|
|
62
|
+
} from "./token-goat-chunk-FNFBKLRD.mjs";
|
|
63
|
+
import {
|
|
64
|
+
init_define_import_meta_env
|
|
65
|
+
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
66
|
+
|
|
67
|
+
// src/hooks_tool_failure.ts
|
|
68
|
+
init_define_import_meta_env();
|
|
69
|
+
import { createHash } from "node:crypto";
|
|
70
|
+
import { existsSync, readFileSync as readFileSync2, statSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
71
|
+
import { dirname as dirname2, relative } from "node:path";
|
|
72
|
+
|
|
73
|
+
// src/call_streak.ts
|
|
74
|
+
init_define_import_meta_env();
|
|
75
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
76
|
+
import { dirname } from "node:path";
|
|
77
|
+
var SERIAL_GAP_MS = 1e3;
|
|
78
|
+
var SERIAL_READS_BEFORE_HINT = 3;
|
|
79
|
+
var ZERO_HIT_SEARCHES_BEFORE_BRAKE = 3;
|
|
80
|
+
var MAX_BATCH_HINTS_PER_SESSION = 2;
|
|
81
|
+
var MAX_SEARCH_BRAKES_PER_SESSION = 2;
|
|
82
|
+
var STREAK_SUFFIX = ".call-streak";
|
|
83
|
+
var TG_SEARCH_RE = /^(?:token-goat|tg)\s+(?:answer|semantic|symbol|refs|locate)\b/;
|
|
84
|
+
var TG_MEANING_SEARCH_RE = /^(?:token-goat|tg)\s+(?:answer|semantic)\b/;
|
|
85
|
+
var TG_READ_RE = /^(?:token-goat|tg)\s+(?:read|section|outline|skeleton|brief)\b/;
|
|
86
|
+
var WRITE_REDIRECT_RE = /\d?>>?(?!\s*(?:&\d|\/dev\/null\b))/;
|
|
87
|
+
function freshState() {
|
|
88
|
+
return { promptId: "", lastReadPostAt: 0, inFlight: false, serialRun: 0, batchShownInRun: false, batchShown: 0, batchVerdict: "none", zeroHits: 0, brakeShownInRun: false, brakeShown: 0, brakeVerdict: false };
|
|
89
|
+
}
|
|
90
|
+
function readState(target) {
|
|
91
|
+
const state = freshState();
|
|
92
|
+
try {
|
|
93
|
+
const parsed = JSON.parse(readFileSync(target, "utf8"));
|
|
94
|
+
if (parsed === null || typeof parsed !== "object") return state;
|
|
95
|
+
const p = parsed;
|
|
96
|
+
for (const key of Object.keys(state)) {
|
|
97
|
+
if (typeof p[key] === typeof state[key]) state[key] = p[key];
|
|
98
|
+
}
|
|
99
|
+
if (!["none", "next_turn", "second_call"].includes(state.batchVerdict)) state.batchVerdict = "none";
|
|
100
|
+
} catch {
|
|
101
|
+
}
|
|
102
|
+
return state;
|
|
103
|
+
}
|
|
104
|
+
function writeState(target, state) {
|
|
105
|
+
try {
|
|
106
|
+
ensureDirSync(dirname(target));
|
|
107
|
+
writeFileSync(target, JSON.stringify(state), "utf8");
|
|
108
|
+
} catch {
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
var MUTATING = { readOnly: false, search: false, meaningSearch: false };
|
|
112
|
+
function isPassThroughStage(stage) {
|
|
113
|
+
const head = (stage.split(/\s/, 1)[0] ?? "").replace(/^.*[/\\]/, "");
|
|
114
|
+
return head !== "tee" && PIPELINE_PASSTHROUGH_HEADS.has(head);
|
|
115
|
+
}
|
|
116
|
+
function bashCallKind(event) {
|
|
117
|
+
const raw = extractCommand(event);
|
|
118
|
+
if (raw === void 0) return MUTATING;
|
|
119
|
+
const cmd = stripCommandPrefix(unwrapCompressCommand(raw) ?? raw);
|
|
120
|
+
const stages = splitShellSegments(cmd).map((s) => stripLeadingAssignments(s.trim())).filter((s) => s !== "");
|
|
121
|
+
if (stages.length === 0 || stages.some((s) => WRITE_REDIRECT_RE.test(s))) return MUTATING;
|
|
122
|
+
const searches = stages.filter((s) => SEARCH_COMMAND_RE.test(s) || TG_SEARCH_RE.test(s));
|
|
123
|
+
const readOnly = pureFileReadPath(cmd) !== null || stages.every((s) => SEARCH_COMMAND_RE.test(s) || TG_SEARCH_RE.test(s) || TG_READ_RE.test(s) || isPassThroughStage(s));
|
|
124
|
+
if (!readOnly) return MUTATING;
|
|
125
|
+
return { readOnly, search: searches.length > 0, meaningSearch: TG_MEANING_SEARCH_RE.test(stages[0] ?? "") };
|
|
126
|
+
}
|
|
127
|
+
function callKind(event) {
|
|
128
|
+
switch (event.toolName) {
|
|
129
|
+
case "Read":
|
|
130
|
+
return { readOnly: true, search: false, meaningSearch: false };
|
|
131
|
+
case "Grep":
|
|
132
|
+
case "Glob":
|
|
133
|
+
return { readOnly: true, search: true, meaningSearch: false };
|
|
134
|
+
case "Bash":
|
|
135
|
+
return bashCallKind(event);
|
|
136
|
+
default:
|
|
137
|
+
return MUTATING;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function searchResultCount(event) {
|
|
141
|
+
const structured = structuredResultCount(event.raw);
|
|
142
|
+
if (structured !== null) return structured;
|
|
143
|
+
const text = extractToolResponseField(event.raw, OUTPUT_FIRST_TOOL_RESPONSE_KEYS);
|
|
144
|
+
if (event.toolName === "Bash") return text.trim() === "" ? 0 : 1;
|
|
145
|
+
return text === "" ? null : estimateResultCount(text);
|
|
146
|
+
}
|
|
147
|
+
function batchHintText(run) {
|
|
148
|
+
return `[token-goat] ${run} reads/searches in a row each waited a full turn. Issue independent reads and searches together in one message.`;
|
|
149
|
+
}
|
|
150
|
+
function searchBrakeText(misses) {
|
|
151
|
+
return `[token-goat] ${misses} searches in a row found nothing. Search by meaning instead of guessing literals: \`token-goat answer "<question>"\` or \`token-goat semantic "<description>"\`.`;
|
|
152
|
+
}
|
|
153
|
+
function trackedLine(event, category, text) {
|
|
154
|
+
const out = applyHintTracking(event, contextOutput(text, [sessionStateKey(event)]), uncorrelatedHint(category));
|
|
155
|
+
if (out.hookType !== "context") return null;
|
|
156
|
+
recordStat("session_hint", 0, 0);
|
|
157
|
+
return out.context;
|
|
158
|
+
}
|
|
159
|
+
function breakStreaks(event, state) {
|
|
160
|
+
if (state.batchVerdict === "second_call") {
|
|
161
|
+
settleSelfScoredHints("read_batch", event, false);
|
|
162
|
+
state.batchVerdict = "none";
|
|
163
|
+
}
|
|
164
|
+
Object.assign(state, { lastReadPostAt: 0, inFlight: false, serialRun: 0, batchShownInRun: false, zeroHits: 0, brakeShownInRun: false });
|
|
165
|
+
}
|
|
166
|
+
function onReadOnlyPre(event, state, kind, now, canSpeak) {
|
|
167
|
+
const serial = !state.inFlight && (state.lastReadPostAt === 0 || now - state.lastReadPostAt > SERIAL_GAP_MS);
|
|
168
|
+
state.inFlight = true;
|
|
169
|
+
if (state.batchVerdict === "second_call") {
|
|
170
|
+
settleSelfScoredHints("read_batch", event, !serial);
|
|
171
|
+
state.batchVerdict = "none";
|
|
172
|
+
} else if (state.batchVerdict === "next_turn" && serial) {
|
|
173
|
+
state.batchVerdict = "second_call";
|
|
174
|
+
}
|
|
175
|
+
if (state.brakeVerdict && kind.search && serial) {
|
|
176
|
+
settleSelfScoredHints("search_brake", event, kind.meaningSearch);
|
|
177
|
+
state.brakeVerdict = false;
|
|
178
|
+
}
|
|
179
|
+
if (!serial) {
|
|
180
|
+
state.serialRun = 0;
|
|
181
|
+
state.batchShownInRun = false;
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
state.serialRun += 1;
|
|
185
|
+
if (state.serialRun < SERIAL_READS_BEFORE_HINT || state.batchShownInRun || state.batchShown >= MAX_BATCH_HINTS_PER_SESSION || !canSpeak) return null;
|
|
186
|
+
state.batchShownInRun = true;
|
|
187
|
+
const line = trackedLine(event, "read_batch", batchHintText(state.serialRun));
|
|
188
|
+
if (line === null) return null;
|
|
189
|
+
state.batchShown += 1;
|
|
190
|
+
state.batchVerdict = "next_turn";
|
|
191
|
+
return line;
|
|
192
|
+
}
|
|
193
|
+
function onSearchMiss(event, state, canSpeak) {
|
|
194
|
+
state.zeroHits += 1;
|
|
195
|
+
if (state.zeroHits < ZERO_HIT_SEARCHES_BEFORE_BRAKE || state.brakeShownInRun || state.brakeShown >= MAX_SEARCH_BRAKES_PER_SESSION || !canSpeak) return null;
|
|
196
|
+
state.brakeShownInRun = true;
|
|
197
|
+
const line = trackedLine(event, "search_brake", searchBrakeText(state.zeroHits));
|
|
198
|
+
if (line === null) return null;
|
|
199
|
+
state.brakeShown += 1;
|
|
200
|
+
state.brakeVerdict = true;
|
|
201
|
+
return line;
|
|
202
|
+
}
|
|
203
|
+
function onReadOnlyPost(event, state, kind, now, canSpeak) {
|
|
204
|
+
state.inFlight = false;
|
|
205
|
+
state.lastReadPostAt = now;
|
|
206
|
+
if (!kind.search) return null;
|
|
207
|
+
const count = searchResultCount(event);
|
|
208
|
+
if (count === null) return null;
|
|
209
|
+
if (count === 0) return onSearchMiss(event, state, canSpeak);
|
|
210
|
+
state.zeroHits = 0;
|
|
211
|
+
state.brakeShownInRun = false;
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
function withStreakState(event, update) {
|
|
215
|
+
if (!event.sessionId) return null;
|
|
216
|
+
const target = sessionSidecarPath(sessionStateKey(event), STREAK_SUFFIX);
|
|
217
|
+
if (target === null) return null;
|
|
218
|
+
const state = readState(target);
|
|
219
|
+
const before = JSON.stringify(state);
|
|
220
|
+
const promptId = event.raw["prompt_id"];
|
|
221
|
+
if (typeof promptId === "string" && promptId !== state.promptId) {
|
|
222
|
+
breakStreaks(event, state);
|
|
223
|
+
if (state.batchVerdict !== "none") settleSelfScoredHints("read_batch", event, null);
|
|
224
|
+
if (state.brakeVerdict) settleSelfScoredHints("search_brake", event, null);
|
|
225
|
+
state.batchVerdict = "none";
|
|
226
|
+
state.brakeVerdict = false;
|
|
227
|
+
state.promptId = promptId;
|
|
228
|
+
}
|
|
229
|
+
const line = update(state);
|
|
230
|
+
if (JSON.stringify(state) !== before) writeState(target, state);
|
|
231
|
+
return line;
|
|
232
|
+
}
|
|
233
|
+
function applyCallStreak(event, output, now) {
|
|
234
|
+
if (event.eventName !== "pre_tool_use" && event.eventName !== "post_tool_use") return output;
|
|
235
|
+
if (output.hookType === "deny") return output;
|
|
236
|
+
try {
|
|
237
|
+
const canSpeak = output.hookType === "pass" || output.hookType === "context";
|
|
238
|
+
const kind = callKind(event);
|
|
239
|
+
const line = withStreakState(event, (state) => {
|
|
240
|
+
if (!kind.readOnly) {
|
|
241
|
+
breakStreaks(event, state);
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
return event.eventName === "pre_tool_use" ? onReadOnlyPre(event, state, kind, now, canSpeak) : onReadOnlyPost(event, state, kind, now, canSpeak);
|
|
245
|
+
});
|
|
246
|
+
if (line === null) return output;
|
|
247
|
+
return output.hookType === "context" ? { ...output, context: `${output.context}
|
|
248
|
+
${line}` } : contextOutput(line);
|
|
249
|
+
} catch {
|
|
250
|
+
return output;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function callStreakAfterFailure(event, reason) {
|
|
254
|
+
try {
|
|
255
|
+
const kind = callKind(event);
|
|
256
|
+
const line = withStreakState(event, (state) => {
|
|
257
|
+
if (!kind.readOnly) {
|
|
258
|
+
breakStreaks(event, state);
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
state.inFlight = false;
|
|
262
|
+
state.lastReadPostAt = Date.now();
|
|
263
|
+
return reason === "search_no_match" ? onSearchMiss(event, state, true) : null;
|
|
264
|
+
});
|
|
265
|
+
return line === null ? null : contextOutput(line);
|
|
266
|
+
} catch {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// src/hooks_verification.ts
|
|
272
|
+
init_define_import_meta_env();
|
|
273
|
+
var VERIFICATION_WORD = /test|jest|lint|check|build|compile|verify|tsc|ruff|clippy|mypy|pyright|\bvet\b/i;
|
|
274
|
+
function mayBeVerificationCommand(command) {
|
|
275
|
+
return VERIFICATION_WORD.test(command);
|
|
276
|
+
}
|
|
277
|
+
registerHook("stop", async (event) => (await import("./token-goat-chunk-OS5EM5PP.mjs")).stopHandler(event), { advisory: true });
|
|
278
|
+
async function noteFailedVerificationHandler(event) {
|
|
279
|
+
const executed = getToolInput(event)["command"];
|
|
280
|
+
const command = typeof executed === "string" ? unwrapCompressCommand(executed) ?? executed : null;
|
|
281
|
+
if (getToolName(event)?.toLowerCase() === "bash" && command !== null && mayBeVerificationCommand(command)) {
|
|
282
|
+
const [failure, verification] = await Promise.all([import("./token-goat-chunk-XZSUHBVS.mjs"), import("./token-goat-chunk-QFNQXSDT.mjs")]);
|
|
283
|
+
const errorText = failure.extractFailureText(event.raw);
|
|
284
|
+
if (errorText !== "") verification.noteFailedVerificationRun(command, errorText, event.raw["is_interrupt"] === true);
|
|
285
|
+
}
|
|
286
|
+
return passOutput();
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// src/hooks_tool_failure.ts
|
|
290
|
+
var FAILURE_SUFFIX = ".tool-failures";
|
|
291
|
+
var MAX_TRACKED_FAILURES = 64;
|
|
292
|
+
var SIGNATURE_ERROR_CHARS = 200;
|
|
293
|
+
var LEDGER_VERSION = 2;
|
|
294
|
+
function failureSignature(toolName, errorText) {
|
|
295
|
+
const tool = toolName === void 0 || toolName === "" ? "unknown" : toolName;
|
|
296
|
+
const normalized = errorText.replace(/\s+/g, " ").trim().slice(0, SIGNATURE_ERROR_CHARS);
|
|
297
|
+
return `${tool} :: ${normalized}`;
|
|
298
|
+
}
|
|
299
|
+
function extractFailureText(raw) {
|
|
300
|
+
for (const key of ["error", "errorMessage", "tool_error", "toolError", "message", "reason"]) {
|
|
301
|
+
const value = raw[key];
|
|
302
|
+
if (typeof value === "string" && value.trim() !== "") return value;
|
|
303
|
+
}
|
|
304
|
+
const response = raw["tool_response"] ?? raw["toolResponse"];
|
|
305
|
+
if (typeof response === "string" && response.trim() !== "") return response;
|
|
306
|
+
if (response !== null && typeof response === "object") {
|
|
307
|
+
const nested = response["error"];
|
|
308
|
+
if (typeof nested === "string" && nested.trim() !== "") return nested;
|
|
309
|
+
}
|
|
310
|
+
return "";
|
|
311
|
+
}
|
|
312
|
+
function ledgerPath(sessionId) {
|
|
313
|
+
return sessionSidecarPath(sessionId, FAILURE_SUFFIX);
|
|
314
|
+
}
|
|
315
|
+
function readLedger(target) {
|
|
316
|
+
try {
|
|
317
|
+
const parsed = JSON.parse(readFileSync2(target, "utf8"));
|
|
318
|
+
if (parsed !== null && typeof parsed === "object") {
|
|
319
|
+
if (parsed.version !== LEDGER_VERSION) return { seen: {}, order: [] };
|
|
320
|
+
const seen = parsed.seen;
|
|
321
|
+
const order = parsed.order;
|
|
322
|
+
if (seen !== null && typeof seen === "object" && Array.isArray(order)) {
|
|
323
|
+
return { seen, order: order.filter((k) => typeof k === "string") };
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
} catch {
|
|
327
|
+
}
|
|
328
|
+
return { seen: {}, order: [] };
|
|
329
|
+
}
|
|
330
|
+
function writeLedger(target, ledger) {
|
|
331
|
+
try {
|
|
332
|
+
ensureDirSync(dirname2(target));
|
|
333
|
+
writeFileSync2(target, JSON.stringify({ version: LEDGER_VERSION, ...ledger }), "utf8");
|
|
334
|
+
} catch {
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
var REPEAT_NOTICE_EXEMPT = /* @__PURE__ */ new Set([
|
|
338
|
+
// Refusals and stops. Claude Code never delivers a refused call to this event (a PreToolUse deny fired no PostToolUseFailure in a 2.1.281 capture), so these guard the other harnesses that route failures here.
|
|
339
|
+
"interrupted",
|
|
340
|
+
// the payload's is_interrupt flag; the census has 0 rows because an interrupt never surfaces as an is_error result
|
|
341
|
+
"tg_deny",
|
|
342
|
+
// 2,762 rows, 283 repeats, 13 with the same input: the deny names the command to run instead
|
|
343
|
+
"tg_content_delivered",
|
|
344
|
+
// a deny whose text is the content (a Skill's compact slice or heading tree, a served Read sidecar): the call did its job, so there is nothing to retry
|
|
345
|
+
"hook_deny",
|
|
346
|
+
// 5 rows: another hook's refusal, with its own instruction
|
|
347
|
+
"user_rejected",
|
|
348
|
+
// 73 rows, 21 repeats, 1 with the same input
|
|
349
|
+
"auto_mode_blocked",
|
|
350
|
+
// 1 row
|
|
351
|
+
// Generic wording: a repeat was a different call that failed the same way.
|
|
352
|
+
"search_no_match",
|
|
353
|
+
// 99 repeats, 0 with the same input: every empty grep prints the same bare `Exit code 1`
|
|
354
|
+
"command_timeout",
|
|
355
|
+
// 41 repeats, 0 with the same input
|
|
356
|
+
"subagent_limit",
|
|
357
|
+
// 27 repeats, 1 with the same input; the harness's own text already says not to retry
|
|
358
|
+
"input_validation"
|
|
359
|
+
// 23 repeats, 0 with the same input
|
|
360
|
+
]);
|
|
361
|
+
function repeatFailureNotice(toolName) {
|
|
362
|
+
const tool = toolName === void 0 || toolName === "" ? "This tool" : displaySafeText(toolName);
|
|
363
|
+
return `[token-goat] ${tool} just failed with the same error as an earlier call this session. Retrying it unchanged will fail the same way -- change the arguments, the tool, or the approach.`;
|
|
364
|
+
}
|
|
365
|
+
var nearMissLib;
|
|
366
|
+
async function loadNearMiss() {
|
|
367
|
+
try {
|
|
368
|
+
nearMissLib ??= await import("./token-goat-chunk-5IMLKSOP.mjs");
|
|
369
|
+
} catch {
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
var MAX_EDIT_DIAGNOSE_BYTES = 10 * 1024 * 1024;
|
|
373
|
+
function editOldStrings(event) {
|
|
374
|
+
const input = event.toolInput;
|
|
375
|
+
const out = [];
|
|
376
|
+
for (const key of ["old_string", "old_str", "target", "TargetContent"]) {
|
|
377
|
+
const value = input[key];
|
|
378
|
+
if (typeof value === "string" && value !== "") {
|
|
379
|
+
out.push(value);
|
|
380
|
+
break;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
const edits = input["edits"];
|
|
384
|
+
if (Array.isArray(edits)) {
|
|
385
|
+
for (const entry of edits) {
|
|
386
|
+
const value = entry !== null && typeof entry === "object" ? entry["old_string"] : void 0;
|
|
387
|
+
if (typeof value === "string" && value !== "") out.push(value);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return out;
|
|
391
|
+
}
|
|
392
|
+
function diagnoseEditFailure(event, errorText) {
|
|
393
|
+
const toolName = getToolName(event);
|
|
394
|
+
if (!toolName || !/^(edit|multiedit|str_replace_editor)$/i.test(toolName)) {
|
|
395
|
+
return null;
|
|
396
|
+
}
|
|
397
|
+
const isMultiple = /multiple matches|not unique|found \d+ matches|matches \d+ times|more than one match/i.test(errorText);
|
|
398
|
+
const isNotFound = /no match|not found|could not find|zero matches|string to replace.*not found/i.test(errorText);
|
|
399
|
+
if (!isMultiple && !isNotFound) {
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
const fallbackPath = ["path", "TargetFile"].map((key) => event.toolInput[key]).find((value) => typeof value === "string" && value !== "");
|
|
403
|
+
const filePath = getFilePath(event) ?? (fallbackPath === void 0 ? void 0 : resolveEventPath(event, fallbackPath));
|
|
404
|
+
if (!filePath) return null;
|
|
405
|
+
const oldStrings = editOldStrings(event);
|
|
406
|
+
if (oldStrings.length === 0) return null;
|
|
407
|
+
const absPath = hostPathOfIndexKey(normalizePath(filePath));
|
|
408
|
+
if (!existsSync(absPath)) return null;
|
|
409
|
+
try {
|
|
410
|
+
const stat = statSync(absPath);
|
|
411
|
+
if (stat.size > MAX_EDIT_DIAGNOSE_BYTES) return null;
|
|
412
|
+
const fileContent = readFileSync2(absPath, "utf8");
|
|
413
|
+
const oldString = oldStrings.length === 1 ? oldStrings[0] : oldStrings.find((candidate) => isNotFound ? !fileContent.includes(candidate) : fileContent.indexOf(candidate) !== fileContent.lastIndexOf(candidate));
|
|
414
|
+
if (oldString === void 0) return null;
|
|
415
|
+
const relDisplay = displaySafeText(relative(process.cwd(), absPath).replace(/\\/g, "/") || absPath);
|
|
416
|
+
if (isMultiple) {
|
|
417
|
+
const matchLines = [];
|
|
418
|
+
const lineIndex = buildLineIndex(fileContent);
|
|
419
|
+
let pos = 0;
|
|
420
|
+
while (pos < fileContent.length) {
|
|
421
|
+
const idx = fileContent.indexOf(oldString, pos);
|
|
422
|
+
if (idx === -1) break;
|
|
423
|
+
matchLines.push(offsetToLine(lineIndex, idx));
|
|
424
|
+
pos = idx + Math.max(1, oldString.length);
|
|
425
|
+
}
|
|
426
|
+
if (matchLines.length > 1) {
|
|
427
|
+
const lineList = matchLines.slice(0, 5).join(", ");
|
|
428
|
+
const overflow = matchLines.length > 5 ? ` (+${matchLines.length - 5} more)` : "";
|
|
429
|
+
return `[token-goat] Edit failed: string matched ${matchLines.length} times in ${relDisplay} on lines ${lineList}${overflow}. Include 2-3 lines of surrounding context to make old_str unique.`;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
if (isNotFound) {
|
|
433
|
+
const normOld = oldString.replace(/\r\n/g, "\n");
|
|
434
|
+
const normFile = fileContent.replace(/\r\n/g, "\n");
|
|
435
|
+
if (normFile.includes(normOld)) {
|
|
436
|
+
return `[token-goat] Edit failed: string not found in ${relDisplay}, but matches with normalized line endings. Check CRLF vs LF line endings or whitespace.`;
|
|
437
|
+
}
|
|
438
|
+
const nearMiss = nearMissLib?.findNearMiss(fileContent, oldString) ?? null;
|
|
439
|
+
const nearAdvice = nearMiss === null ? null : nearMissLib?.describeNearMiss(fileContent, relDisplay, nearMiss) ?? null;
|
|
440
|
+
if (nearAdvice !== null) return nearAdvice;
|
|
441
|
+
const firstLine = oldString.split(/\r?\n/)[0]?.trim() ?? "";
|
|
442
|
+
if (firstLine.length >= 10) {
|
|
443
|
+
const fileLines = fileContent.split("\n");
|
|
444
|
+
const similarLines = [];
|
|
445
|
+
for (let i = 0; i < fileLines.length; i++) {
|
|
446
|
+
const lineText = fileLines[i];
|
|
447
|
+
if (lineText !== void 0 && lineText.includes(firstLine)) {
|
|
448
|
+
similarLines.push(i + 1);
|
|
449
|
+
if (similarLines.length >= 3) break;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
if (similarLines.length > 0) {
|
|
453
|
+
return `[token-goat] Edit failed: string not found in ${relDisplay}. A similar line was found on line ${similarLines.join(", ")} \u2014 view that range to copy exact text.`;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return `[token-goat] Edit failed: string not found in ${relDisplay}. View the target lines to copy the exact current content and indentation.`;
|
|
457
|
+
}
|
|
458
|
+
} catch {
|
|
459
|
+
}
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
function editAdviceOutput(event, text) {
|
|
463
|
+
const out = contextOutput(text);
|
|
464
|
+
return nearMissLib?.isNearMissAdvice(text) === true ? applyHintTracking(event, out, uncorrelatedHint("edit_near_miss")) : out;
|
|
465
|
+
}
|
|
466
|
+
var RECOVERY_SKIPPED = /* @__PURE__ */ new Set(["shell_syntax_error", "sleep_blocked"]);
|
|
467
|
+
function newSlot() {
|
|
468
|
+
return { lines: [], recovery: null, pathMiss: null };
|
|
469
|
+
}
|
|
470
|
+
function withExtraLines(base, lines) {
|
|
471
|
+
if (lines.length === 0) return base;
|
|
472
|
+
const extra = lines.join("\n");
|
|
473
|
+
if (base.hookType === "context") return contextOutput([base.context, extra].join("\n"), base.correlators);
|
|
474
|
+
return base.hookType === "pass" ? contextOutput(extra) : base;
|
|
475
|
+
}
|
|
476
|
+
function postToolUseFailureHandler(event) {
|
|
477
|
+
return adviseOnFailure(event, newSlot());
|
|
478
|
+
}
|
|
479
|
+
async function postToolUseFailureWithExtras(event) {
|
|
480
|
+
const slot = newSlot();
|
|
481
|
+
const toolName = getToolName(event);
|
|
482
|
+
if (toolName !== void 0 && /^(edit|multiedit|str_replace_editor)$/i.test(toolName)) await loadNearMiss();
|
|
483
|
+
const base = adviseOnFailure(event, slot);
|
|
484
|
+
try {
|
|
485
|
+
if (slot.recovery !== null) {
|
|
486
|
+
const { recoveryAfterFailure } = await import("./token-goat-chunk-FDSREWLX.mjs");
|
|
487
|
+
const recovery = recoveryAfterFailure(event, { command: slot.recovery.command, errorText: slot.recovery.errorText });
|
|
488
|
+
if (recovery !== null) slot.lines.push(recovery);
|
|
489
|
+
}
|
|
490
|
+
if (slot.pathMiss !== null) {
|
|
491
|
+
const { pathMissAfterFailure } = await import("./token-goat-chunk-3EZRNKTK.mjs");
|
|
492
|
+
const pathMiss = pathMissAfterFailure(event, slot.pathMiss);
|
|
493
|
+
if (pathMiss !== null) slot.lines.push(pathMiss);
|
|
494
|
+
}
|
|
495
|
+
} catch {
|
|
496
|
+
}
|
|
497
|
+
return withExtraLines(base, slot.lines);
|
|
498
|
+
}
|
|
499
|
+
function adviseOnFailure(event, slot) {
|
|
500
|
+
try {
|
|
501
|
+
const errorText = extractFailureText(event.raw);
|
|
502
|
+
if (errorText === "") return passOutput();
|
|
503
|
+
const toolName = getToolName(event);
|
|
504
|
+
const executed = getToolInput(event)["command"];
|
|
505
|
+
const command = typeof executed === "string" ? unwrapCompressCommand(executed) ?? executed : executed;
|
|
506
|
+
const verdict = classifyToolError(toolName, errorText, { isInterrupt: event.raw["is_interrupt"] === true, ...typeof command === "string" ? { command } : {} });
|
|
507
|
+
recordStat("tool_failure", 0, 0, void 0, `tool=${(toolName ?? "unknown").replace(/\s+/g, "_")} class=${verdict.kind} reason=${verdict.reason}`);
|
|
508
|
+
const streakLine = callStreakAfterFailure(event, verdict.reason);
|
|
509
|
+
if (toolName === "Bash" && typeof command === "string" && event.raw["is_interrupt"] !== true && !REPEAT_NOTICE_EXEMPT.has(verdict.reason) && !RECOVERY_SKIPPED.has(verdict.reason)) {
|
|
510
|
+
slot.recovery = { toolName, errorText, command };
|
|
511
|
+
}
|
|
512
|
+
if (verdict.reason === "path_not_found" && event.raw["is_interrupt"] !== true) {
|
|
513
|
+
slot.pathMiss = { toolName, errorText };
|
|
514
|
+
}
|
|
515
|
+
if (REPEAT_NOTICE_EXEMPT.has(verdict.reason)) return streakLine ?? passOutput();
|
|
516
|
+
if (!event.sessionId) return passOutput();
|
|
517
|
+
const target = ledgerPath(event.sessionId);
|
|
518
|
+
if (target === null) return passOutput();
|
|
519
|
+
const signature = createHash("sha256").update(failureSignature(toolName, redactSecrets(errorText).text)).digest("hex");
|
|
520
|
+
const ledger = readLedger(target);
|
|
521
|
+
const priorState = ledger.seen[signature];
|
|
522
|
+
const editDiagnostic = diagnoseEditFailure(event, errorText);
|
|
523
|
+
const sqlDiagnostic = diagnoseSqlFailure(event, errorText);
|
|
524
|
+
if (priorState === void 0) {
|
|
525
|
+
ledger.seen[signature] = false;
|
|
526
|
+
ledger.order.push(signature);
|
|
527
|
+
while (ledger.order.length > MAX_TRACKED_FAILURES) {
|
|
528
|
+
const evicted = ledger.order.shift();
|
|
529
|
+
if (evicted !== void 0) delete ledger.seen[evicted];
|
|
530
|
+
}
|
|
531
|
+
writeLedger(target, ledger);
|
|
532
|
+
if (editDiagnostic !== null) {
|
|
533
|
+
ledger.seen[signature] = true;
|
|
534
|
+
writeLedger(target, ledger);
|
|
535
|
+
return editAdviceOutput(event, editDiagnostic);
|
|
536
|
+
}
|
|
537
|
+
if (sqlDiagnostic !== null) {
|
|
538
|
+
ledger.seen[signature] = true;
|
|
539
|
+
writeLedger(target, ledger);
|
|
540
|
+
return contextOutput(sqlDiagnostic);
|
|
541
|
+
}
|
|
542
|
+
return passOutput();
|
|
543
|
+
}
|
|
544
|
+
if (priorState) return passOutput();
|
|
545
|
+
ledger.seen[signature] = true;
|
|
546
|
+
writeLedger(target, ledger);
|
|
547
|
+
if (editDiagnostic !== null) {
|
|
548
|
+
return editAdviceOutput(event, editDiagnostic);
|
|
549
|
+
}
|
|
550
|
+
if (sqlDiagnostic !== null) {
|
|
551
|
+
return contextOutput(sqlDiagnostic);
|
|
552
|
+
}
|
|
553
|
+
return contextOutput(repeatFailureNotice(toolName));
|
|
554
|
+
} catch {
|
|
555
|
+
return passOutput();
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
registerHook("post_tool_use_failure", noteFailedVerificationHandler, { advisory: true });
|
|
559
|
+
registerHook("post_tool_use_failure", postToolUseFailureWithExtras);
|
|
560
|
+
|
|
561
|
+
export {
|
|
562
|
+
applyCallStreak,
|
|
563
|
+
MAX_TRACKED_FAILURES,
|
|
564
|
+
failureSignature,
|
|
565
|
+
extractFailureText,
|
|
566
|
+
REPEAT_NOTICE_EXEMPT,
|
|
567
|
+
repeatFailureNotice,
|
|
568
|
+
loadNearMiss,
|
|
569
|
+
diagnoseEditFailure,
|
|
570
|
+
postToolUseFailureHandler,
|
|
571
|
+
postToolUseFailureWithExtras,
|
|
572
|
+
mayBeVerificationCommand
|
|
573
|
+
};
|