token-goat 2.9.30 → 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.
Files changed (172) hide show
  1. package/README.md +24 -7
  2. package/SECURITY.md +10 -2
  3. package/THIRD_PARTY_NOTICES.md +1 -1
  4. package/dist/native/linux-arm64/tg-hook +0 -0
  5. package/dist/native/linux-x64/tg-hook +0 -0
  6. package/dist/native/win32-arm64/tg-hook.exe +0 -0
  7. package/dist/native/win32-x64/tg-hook.exe +0 -0
  8. package/dist/{token-goat-chunk-QSBRTGM2.mjs → token-goat-chunk-25TRAWET.mjs} +17 -7
  9. package/dist/token-goat-chunk-2KXO6V2B.mjs +203 -0
  10. package/dist/{token-goat-chunk-IVKIZWAB.mjs → token-goat-chunk-2M7E4PF7.mjs} +41 -12
  11. package/dist/{token-goat-chunk-SMVRN2HU.mjs → token-goat-chunk-2UPZGKKY.mjs} +2 -2
  12. package/dist/token-goat-chunk-2WLPWKHV.mjs +135 -0
  13. package/dist/token-goat-chunk-2XBMMDBD.mjs +126 -0
  14. package/dist/token-goat-chunk-32ZOY4N5.mjs +23 -0
  15. package/dist/token-goat-chunk-3EZRNKTK.mjs +188 -0
  16. package/dist/token-goat-chunk-4ADZHI7J.mjs +63 -0
  17. package/dist/token-goat-chunk-4GBVPH3D.mjs +242 -0
  18. package/dist/{token-goat-chunk-KWPNJBDH.mjs → token-goat-chunk-4GILLLWY.mjs} +7 -4
  19. package/dist/{token-goat-chunk-67TQJ76B.mjs → token-goat-chunk-4NAPX7BA.mjs} +36 -3
  20. package/dist/{token-goat-chunk-PU7V3FD6.mjs → token-goat-chunk-4SC7UJYV.mjs} +3354 -2553
  21. package/dist/token-goat-chunk-4SMRO4TO.mjs +366 -0
  22. package/dist/{token-goat-chunk-AFLYLHDH.mjs → token-goat-chunk-4ZBFWLXF.mjs} +283 -427
  23. package/dist/{token-goat-chunk-JDWCRD6M.mjs → token-goat-chunk-57BIAXJL.mjs} +73 -40
  24. package/dist/token-goat-chunk-5AC66HNP.mjs +115 -0
  25. package/dist/token-goat-chunk-5IMLKSOP.mjs +145 -0
  26. package/dist/token-goat-chunk-646E6U44.mjs +398 -0
  27. package/dist/token-goat-chunk-65N4RHP4.mjs +33 -0
  28. package/dist/{token-goat-chunk-JN4XMLSD.mjs → token-goat-chunk-6DG6HWP3.mjs} +8 -2
  29. package/dist/token-goat-chunk-6ENQSNRZ.mjs +573 -0
  30. package/dist/token-goat-chunk-6ZY4GNF2.mjs +91 -0
  31. package/dist/{token-goat-chunk-VPBBTSJR.mjs → token-goat-chunk-76FGDLRO.mjs} +262 -255
  32. package/dist/{token-goat-chunk-7IN2MKDS.mjs → token-goat-chunk-7EZTZOMC.mjs} +121 -289
  33. package/dist/{token-goat-chunk-OJBNYTJP.mjs → token-goat-chunk-7MAOA6X4.mjs} +640 -80
  34. package/dist/token-goat-chunk-7R2ZVVAX.mjs +218 -0
  35. package/dist/{token-goat-chunk-PD5VKH46.mjs → token-goat-chunk-AUNGYYQX.mjs} +2 -2
  36. package/dist/{token-goat-chunk-HG45AF2B.mjs → token-goat-chunk-AUQYRMMH.mjs} +794 -37
  37. package/dist/token-goat-chunk-B3PEKBYG.mjs +128 -0
  38. package/dist/{token-goat-chunk-A3CK6N5Z.mjs → token-goat-chunk-BA4HI6BW.mjs} +1309 -110
  39. package/dist/{token-goat-chunk-JB6QN6VF.mjs → token-goat-chunk-BFCWY73P.mjs} +59 -23
  40. package/dist/{token-goat-chunk-B45VMIIH.mjs → token-goat-chunk-BWGFUZZE.mjs} +7 -5
  41. package/dist/{token-goat-chunk-P4QMM4WK.mjs → token-goat-chunk-C75NA7PL.mjs} +50 -23
  42. package/dist/token-goat-chunk-CBIQ7WTD.mjs +87 -0
  43. package/dist/token-goat-chunk-CETM74KC.mjs +307 -0
  44. package/dist/{token-goat-chunk-H2PHHGM5.mjs → token-goat-chunk-CIMQ2BB3.mjs} +57 -12
  45. package/dist/{token-goat-chunk-N2NMER56.mjs → token-goat-chunk-CJLS3CDL.mjs} +46 -4
  46. package/dist/{token-goat-chunk-VES7EL7O.mjs → token-goat-chunk-CO3UYX6G.mjs} +1 -1
  47. package/dist/token-goat-chunk-COPNXRJM.mjs +154 -0
  48. package/dist/token-goat-chunk-CSJ5L3NL.mjs +479 -0
  49. package/dist/{token-goat-chunk-4LCCNRTG.mjs → token-goat-chunk-CVCEVUGK.mjs} +8 -6
  50. package/dist/{token-goat-chunk-B2RZZCSS.mjs → token-goat-chunk-CXHOFN7R.mjs} +37 -20
  51. package/dist/token-goat-chunk-D735C4QM.mjs +603 -0
  52. package/dist/{token-goat-chunk-APGZXSPS.mjs → token-goat-chunk-DGS2LVNA.mjs} +47 -30
  53. package/dist/{token-goat-chunk-54K3EUV3.mjs → token-goat-chunk-DOWRSMWO.mjs} +1 -1
  54. package/dist/token-goat-chunk-E45INMY3.mjs +71 -0
  55. package/dist/token-goat-chunk-EC5F37F4.mjs +244 -0
  56. package/dist/{token-goat-chunk-XTQAOTSO.mjs → token-goat-chunk-EDBDRVH5.mjs} +4 -1
  57. package/dist/{token-goat-chunk-5BCIJXMO.mjs → token-goat-chunk-EELTBKDM.mjs} +14 -10
  58. package/dist/{token-goat-chunk-W3QCJS6G.mjs → token-goat-chunk-F4HYL64R.mjs} +8 -6
  59. package/dist/token-goat-chunk-F6PAUIEK.mjs +624 -0
  60. package/dist/token-goat-chunk-FDSREWLX.mjs +692 -0
  61. package/dist/token-goat-chunk-GGGG7RWB.mjs +236 -0
  62. package/dist/{token-goat-chunk-C63JQV5K.mjs → token-goat-chunk-GL3ETKSC.mjs} +233 -15
  63. package/dist/token-goat-chunk-GVB2MUST.mjs +1298 -0
  64. package/dist/token-goat-chunk-GWFLAUMQ.mjs +307 -0
  65. package/dist/{token-goat-chunk-ZEJVMUQH.mjs → token-goat-chunk-HLPW63A7.mjs} +2 -2
  66. package/dist/{token-goat-chunk-GOLEOXZP.mjs → token-goat-chunk-HU4TORC5.mjs} +44 -26
  67. package/dist/{token-goat-chunk-Z57YODA2.mjs → token-goat-chunk-I7VKZZAW.mjs} +2 -2
  68. package/dist/{token-goat-chunk-NYKZLXMK.mjs → token-goat-chunk-IA6XSPE3.mjs} +6 -6
  69. package/dist/{token-goat-chunk-E3OQX2XT.mjs → token-goat-chunk-IAGXMHIK.mjs} +81 -42
  70. package/dist/{token-goat-chunk-HYBFA5X3.mjs → token-goat-chunk-IK2DRMFX.mjs} +24 -68
  71. package/dist/{token-goat-chunk-COBQGL5S.mjs → token-goat-chunk-INNPTRUX.mjs} +249 -299
  72. package/dist/{token-goat-chunk-7NADEDKJ.mjs → token-goat-chunk-JJ5BX4F4.mjs} +6 -1
  73. package/dist/{token-goat-chunk-PEPTHRFF.mjs → token-goat-chunk-JVFSHVFJ.mjs} +6 -6
  74. package/dist/token-goat-chunk-KGEFFSHD.mjs +50 -0
  75. package/dist/token-goat-chunk-KQBLRPBN.mjs +433 -0
  76. package/dist/{token-goat-chunk-Q5VTGRH7.mjs → token-goat-chunk-LCNQ2CNN.mjs} +55 -319
  77. package/dist/token-goat-chunk-M3LFJDPU.mjs +58 -0
  78. package/dist/token-goat-chunk-M52KPT3C.mjs +87 -0
  79. package/dist/token-goat-chunk-MBEG42H7.mjs +150 -0
  80. package/dist/{token-goat-chunk-EVC4TOLE.mjs → token-goat-chunk-METECDOH.mjs} +3 -12
  81. package/dist/{token-goat-chunk-T4FK7VOV.mjs → token-goat-chunk-MHX7XCC3.mjs} +2 -1
  82. package/dist/token-goat-chunk-N5LSOVSU.mjs +137 -0
  83. package/dist/{token-goat-chunk-LOBGHXPB.mjs → token-goat-chunk-N5MMR2IW.mjs} +1 -1
  84. package/dist/token-goat-chunk-N7B3JQ2C.mjs +160 -0
  85. package/dist/{token-goat-chunk-RHXKCZX3.mjs → token-goat-chunk-NISNMD7T.mjs} +2182 -2959
  86. package/dist/token-goat-chunk-NMD42SFQ.mjs +434 -0
  87. package/dist/token-goat-chunk-NOSS5VWY.mjs +174 -0
  88. package/dist/{token-goat-chunk-KQNZDCBD.mjs → token-goat-chunk-NSNSPPBG.mjs} +25 -3
  89. package/dist/token-goat-chunk-OBOFIHKN.mjs +38 -0
  90. package/dist/token-goat-chunk-OBRFJ5O5.mjs +76 -0
  91. package/dist/{token-goat-chunk-JTQQGXZH.mjs → token-goat-chunk-ODBT2USM.mjs} +124 -57
  92. package/dist/token-goat-chunk-OS5EM5PP.mjs +107 -0
  93. package/dist/token-goat-chunk-OUKDTVNU.mjs +1178 -0
  94. package/dist/token-goat-chunk-OXFMP75N.mjs +566 -0
  95. package/dist/{token-goat-chunk-DZX2YDPT.mjs → token-goat-chunk-OYIYKDDT.mjs} +2 -2
  96. package/dist/{token-goat-chunk-QCLDAQTS.mjs → token-goat-chunk-P6HQSWQ3.mjs} +50 -53
  97. package/dist/token-goat-chunk-P6VGNTQT.mjs +71 -0
  98. package/dist/{token-goat-chunk-7BXSNBY5.mjs → token-goat-chunk-PFWIMH2E.mjs} +23 -15
  99. package/dist/token-goat-chunk-PJZXIS3G.mjs +39 -0
  100. package/dist/token-goat-chunk-PUO5INXP.mjs +606 -0
  101. package/dist/{token-goat-chunk-GFBSN7BD.mjs → token-goat-chunk-PX5PQWTY.mjs} +22 -250
  102. package/dist/token-goat-chunk-Q5QDBC6O.mjs +111 -0
  103. package/dist/token-goat-chunk-QFNQXSDT.mjs +40 -0
  104. package/dist/{token-goat-chunk-FBNQNSJK.mjs → token-goat-chunk-QH7YVYOY.mjs} +2198 -2782
  105. package/dist/{token-goat-chunk-64FBPDTK.mjs → token-goat-chunk-QLMUHEPB.mjs} +12 -9
  106. package/dist/{token-goat-chunk-RZRTDST7.mjs → token-goat-chunk-QQOJIHL3.mjs} +37 -11
  107. package/dist/{token-goat-chunk-XKI4SEMX.mjs → token-goat-chunk-QQTWJY2O.mjs} +19 -0
  108. package/dist/{token-goat-chunk-U4N3BN2W.mjs → token-goat-chunk-QYHO5CPH.mjs} +3 -2
  109. package/dist/token-goat-chunk-RELAVWAD.mjs +27 -0
  110. package/dist/{token-goat-chunk-ETBHVDB6.mjs → token-goat-chunk-RSLPOBKQ.mjs} +22 -11
  111. package/dist/token-goat-chunk-SAMFDIS2.mjs +712 -0
  112. package/dist/token-goat-chunk-SDELXLDM.mjs +48 -0
  113. package/dist/{token-goat-chunk-4JJS54TR.mjs → token-goat-chunk-SOAFZNNZ.mjs} +161 -38
  114. package/dist/{token-goat-chunk-664RTTUV.mjs → token-goat-chunk-SRTHT7KV.mjs} +21 -16
  115. package/dist/{token-goat-chunk-4FVIAHSI.mjs → token-goat-chunk-T5P5ACNQ.mjs} +7 -6
  116. package/dist/token-goat-chunk-T5YGG4V3.mjs +45 -0
  117. package/dist/token-goat-chunk-TAUZ4OFS.mjs +110 -0
  118. package/dist/{token-goat-chunk-COTXZHTS.mjs → token-goat-chunk-TM6MC754.mjs} +4 -3
  119. package/dist/token-goat-chunk-TWUKBOMP.mjs +72 -0
  120. package/dist/{token-goat-chunk-3CHUNJ2O.mjs → token-goat-chunk-U2KSB4SG.mjs} +8 -5
  121. package/dist/{token-goat-chunk-3Z5S4KGM.mjs → token-goat-chunk-U4WHMG6Y.mjs} +29 -49
  122. package/dist/{token-goat-chunk-PY533T7F.mjs → token-goat-chunk-UGJHGR5A.mjs} +21 -15
  123. package/dist/{token-goat-chunk-CYCEYAEO.mjs → token-goat-chunk-UOUDVA5U.mjs} +1 -1
  124. package/dist/{token-goat-chunk-JDHE26RP.mjs → token-goat-chunk-URRJ33GR.mjs} +16 -5
  125. package/dist/{token-goat-chunk-56EIMS3E.mjs → token-goat-chunk-UZOROKIS.mjs} +23 -17
  126. package/dist/{token-goat-chunk-CZ3LUXYZ.mjs → token-goat-chunk-VIHGGGEI.mjs} +427 -308
  127. package/dist/token-goat-chunk-VTJLAA7P.mjs +21 -0
  128. package/dist/token-goat-chunk-VWDXLT4F.mjs +678 -0
  129. package/dist/{token-goat-chunk-YARZFCZS.mjs → token-goat-chunk-VWZA2H4P.mjs} +62 -53
  130. package/dist/{token-goat-chunk-SQSSNQPE.mjs → token-goat-chunk-VXEXMJDL.mjs} +3979 -4745
  131. package/dist/token-goat-chunk-WBA5SKT4.mjs +547 -0
  132. package/dist/{token-goat-chunk-SJHWVNDQ.mjs → token-goat-chunk-WDH44VAU.mjs} +7 -4
  133. package/dist/token-goat-chunk-X2SUP3EI.mjs +107 -0
  134. package/dist/token-goat-chunk-X3BELZSJ.mjs +125 -0
  135. package/dist/{token-goat-chunk-FZ3NEW5O.mjs → token-goat-chunk-XLRBNZCC.mjs} +13 -8
  136. package/dist/{token-goat-chunk-Z44YO3QZ.mjs → token-goat-chunk-XRKUX6CM.mjs} +1 -1
  137. package/dist/token-goat-chunk-XX6O25RN.mjs +82 -0
  138. package/dist/token-goat-chunk-XZSUHBVS.mjs +65 -0
  139. package/dist/{token-goat-chunk-WY3L4DVT.mjs → token-goat-chunk-Y2ZTQOCL.mjs} +13 -8
  140. package/dist/{token-goat-chunk-UQ5UK2T7.mjs → token-goat-chunk-YB4VMGK2.mjs} +1 -1
  141. package/dist/token-goat-chunk-YBIIY3HR.mjs +51 -0
  142. package/dist/{token-goat-chunk-ZQSJMO2R.mjs → token-goat-chunk-YHVDKQBR.mjs} +105 -105
  143. package/dist/{token-goat-chunk-H2K3QP6H.mjs → token-goat-chunk-YJB5XLWI.mjs} +8 -6
  144. package/dist/{token-goat-chunk-ZCDTCVIS.mjs → token-goat-chunk-YKB6AQG3.mjs} +5 -2
  145. package/dist/token-goat-chunk-YMTG2YA5.mjs +35 -0
  146. package/dist/token-goat-chunk-YPBZYQRV.mjs +40 -0
  147. package/dist/{token-goat-chunk-HOJLCGDP.mjs → token-goat-chunk-YY6AVUFL.mjs} +2033 -2251
  148. package/dist/token-goat-chunk-Z7N5OMMP.mjs +98 -0
  149. package/dist/token-goat-chunk-ZNMNUPAZ.mjs +938 -0
  150. package/dist/token-goat-hook-client.cjs +1 -1
  151. package/dist/token-goat-hook-client.mjs +3 -3
  152. package/dist/token-goat-hook.mjs +67 -38
  153. package/dist/token-goat.core.mjs +4 -4
  154. package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
  155. package/docs/cli.md +40 -21
  156. package/docs/install.md +19 -9
  157. package/docs/security.md +5 -3
  158. package/package.json +2 -1
  159. package/dist/token-goat-chunk-5KDMCMF2.mjs +0 -362
  160. package/dist/token-goat-chunk-6QMAS7AB.mjs +0 -42
  161. package/dist/token-goat-chunk-7F2UBPD3.mjs +0 -397
  162. package/dist/token-goat-chunk-ARDNEC2U.mjs +0 -248
  163. package/dist/token-goat-chunk-ATCPY7EQ.mjs +0 -134
  164. package/dist/token-goat-chunk-EFHMMIGP.mjs +0 -68
  165. package/dist/token-goat-chunk-IVALLT3S.mjs +0 -48
  166. package/dist/token-goat-chunk-JDU3EXSU.mjs +0 -65
  167. package/dist/token-goat-chunk-MKPF4CL5.mjs +0 -37
  168. package/dist/token-goat-chunk-RC35RBUL.mjs +0 -312
  169. package/dist/token-goat-chunk-USILZ3T3.mjs +0 -53
  170. package/dist/token-goat-chunk-VL3YIFHZ.mjs +0 -2975
  171. package/dist/token-goat-chunk-XU4P6Z24.mjs +0 -133
  172. package/dist/token-goat-chunk-Y776AENC.mjs +0 -1597
@@ -1,25 +1,28 @@
1
1
  import { createRequire as __cjsRequire } from 'node:module';
2
2
  const require = __cjsRequire(import.meta.url);
3
- import {
4
- estimateTokensFromLength
5
- } from "./token-goat-chunk-JB6QN6VF.mjs";
6
3
  import {
7
4
  recordStat,
8
5
  savedTokensFromBytes
9
- } from "./token-goat-chunk-3Z5S4KGM.mjs";
6
+ } from "./token-goat-chunk-U4WHMG6Y.mjs";
7
+ import {
8
+ estimateTokensFromLength
9
+ } from "./token-goat-chunk-BFCWY73P.mjs";
10
10
  import {
11
11
  countRedactionPlaceholders
12
- } from "./token-goat-chunk-4FVIAHSI.mjs";
12
+ } from "./token-goat-chunk-T5P5ACNQ.mjs";
13
13
  import {
14
14
  loadConfig,
15
15
  ownGet
16
- } from "./token-goat-chunk-7IN2MKDS.mjs";
16
+ } from "./token-goat-chunk-7EZTZOMC.mjs";
17
17
  import {
18
18
  detectHarness
19
- } from "./token-goat-chunk-U4N3BN2W.mjs";
19
+ } from "./token-goat-chunk-QYHO5CPH.mjs";
20
20
  import {
21
21
  registerReset
22
22
  } from "./token-goat-chunk-YZAAZU2S.mjs";
23
+ import {
24
+ echoedValue
25
+ } from "./token-goat-chunk-GGGG7RWB.mjs";
23
26
  import {
24
27
  displaySafeText,
25
28
  neutralizeOutsideFences,
@@ -29,6 +32,253 @@ import {
29
32
  init_define_import_meta_env
30
33
  } from "./token-goat-chunk-A37V4PBF.mjs";
31
34
 
35
+ // src/hooks_common.ts
36
+ init_define_import_meta_env();
37
+ function getToolName(event) {
38
+ return event.toolName;
39
+ }
40
+ function getToolInput(event) {
41
+ return event.toolInput;
42
+ }
43
+ function getFilePath(event) {
44
+ const value = event.toolInput["file_path"];
45
+ if (typeof value === "string" && value !== "") return resolveEventPath(event, value);
46
+ const notebookValue = event.toolInput["notebook_path"];
47
+ return typeof notebookValue === "string" && notebookValue !== "" ? resolveEventPath(event, notebookValue) : void 0;
48
+ }
49
+ function resolveEventPath(event, file) {
50
+ return resolveToolPath(file, getCwd(event));
51
+ }
52
+ function getFilePaths(event) {
53
+ const out = [];
54
+ const list = event.toolInput["file_paths"];
55
+ if (Array.isArray(list)) {
56
+ for (const entry of list) {
57
+ if (typeof entry !== "string" || entry === "") continue;
58
+ const resolved = resolveEventPath(event, entry);
59
+ if (!out.includes(resolved)) out.push(resolved);
60
+ }
61
+ }
62
+ const single = getFilePath(event);
63
+ if (single !== void 0 && !out.includes(single)) out.push(single);
64
+ return out;
65
+ }
66
+ function getCwd(event) {
67
+ const value = event.raw && typeof event.raw === "object" ? event.raw["cwd"] : void 0;
68
+ return typeof value === "string" && value !== "" ? value : void 0;
69
+ }
70
+ function getTranscriptPath(event) {
71
+ const value = event.raw && typeof event.raw === "object" ? event.raw["transcript_path"] : void 0;
72
+ return typeof value === "string" && value !== "" ? value : void 0;
73
+ }
74
+ function extractToolResponseField(raw, keys) {
75
+ const resp = raw["tool_response"];
76
+ if (typeof resp === "string") return resp;
77
+ if (resp !== null && typeof resp === "object") {
78
+ const r = resp;
79
+ const path3 = resolveToolResponseFieldPath(r, keys);
80
+ if (path3 !== null) return readAtPath(r, path3);
81
+ }
82
+ return "";
83
+ }
84
+ var NESTED_TOOL_RESPONSE_PATHS = [["file", "content"]];
85
+ function readAtPath(resp, path3) {
86
+ let cur = resp;
87
+ for (const seg of path3) {
88
+ if (cur === null || typeof cur !== "object") return "";
89
+ cur = cur[seg];
90
+ }
91
+ return typeof cur === "string" ? cur : "";
92
+ }
93
+ function resolveToolResponseFieldPath(resp, keys) {
94
+ for (const key of keys) {
95
+ if (typeof resp[key] === "string" && resp[key] !== "") return [key];
96
+ }
97
+ for (const path3 of NESTED_TOOL_RESPONSE_PATHS) {
98
+ if (readAtPath(resp, path3) !== "") return path3;
99
+ }
100
+ return null;
101
+ }
102
+ function replaceToolResponseField(resp, keys, newText) {
103
+ const path3 = resolveToolResponseFieldPath(resp, keys);
104
+ if (path3 === null) return null;
105
+ const root = { ...resp };
106
+ let cur = root;
107
+ for (let i = 0; i < path3.length - 1; i++) {
108
+ const seg = path3[i];
109
+ const child = cur[seg];
110
+ if (child === null || typeof child !== "object") return null;
111
+ const cloned = { ...child };
112
+ cur[seg] = cloned;
113
+ cur = cloned;
114
+ }
115
+ cur[path3[path3.length - 1]] = newText;
116
+ return root;
117
+ }
118
+ var OUTPUT_FIRST_TOOL_RESPONSE_KEYS = ["output", "content", "text", "body", "stdout", "stderr"];
119
+ var BODY_FIRST_TOOL_RESPONSE_KEYS = ["output", "body", "text", "content", "result"];
120
+ function isMcpErrorResponse(raw) {
121
+ const tr = raw["tool_response"];
122
+ if (!tr || typeof tr !== "object") return false;
123
+ return tr["isError"] === true;
124
+ }
125
+ var MCP_CONTENT_BLOCK_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "resource", "resource_link"]);
126
+ function blocksToText(blocks) {
127
+ if (!Array.isArray(blocks)) return null;
128
+ const parts = [];
129
+ let recognised = false;
130
+ for (const block of blocks) {
131
+ if (!block || typeof block !== "object") continue;
132
+ const rec = block;
133
+ const type = rec["type"];
134
+ if (typeof type === "string" && MCP_CONTENT_BLOCK_TYPES.has(type)) recognised = true;
135
+ if (typeof rec["text"] === "string") {
136
+ parts.push(rec["text"]);
137
+ continue;
138
+ }
139
+ const resource = rec["resource"];
140
+ if (resource !== null && typeof resource === "object") {
141
+ const nested = resource["text"];
142
+ if (typeof nested === "string") parts.push(nested);
143
+ continue;
144
+ }
145
+ if (rec["type"] === "resource_link") {
146
+ const link = ["name", "uri", "description"].map((k) => rec[k]).filter((v) => typeof v === "string" && v !== "");
147
+ if (link.length > 0) parts.push(link.join(" "));
148
+ }
149
+ }
150
+ if (parts.length > 0) return parts.join("\n");
151
+ return recognised ? "" : null;
152
+ }
153
+ function extractToolResultText(raw) {
154
+ const tr = raw["tool_response"];
155
+ if (typeof tr === "string") return tr;
156
+ if (!tr || typeof tr !== "object") return "";
157
+ const bare = blocksToText(tr);
158
+ if (bare !== null) return bare;
159
+ const resp = tr;
160
+ const content = resp["content"];
161
+ const joined = blocksToText(content);
162
+ if (joined !== null) return joined;
163
+ for (const key of ["output", "text", "body"]) {
164
+ if (typeof resp[key] === "string") return resp[key];
165
+ }
166
+ if (typeof content === "string") return content;
167
+ try {
168
+ return JSON.stringify(resp);
169
+ } catch {
170
+ return "";
171
+ }
172
+ }
173
+ function asContentBlocks(value) {
174
+ if (!Array.isArray(value)) return null;
175
+ const blocks = value.filter((b) => b !== null && typeof b === "object");
176
+ const typed = blocks.some((b) => typeof b["type"] === "string" && MCP_CONTENT_BLOCK_TYPES.has(b["type"]));
177
+ return typed ? blocks : null;
178
+ }
179
+ function mcpContentBlocks(raw) {
180
+ const tr = raw["tool_response"];
181
+ if (tr === null || typeof tr !== "object") return null;
182
+ return asContentBlocks(tr) ?? asContentBlocks(tr["content"]);
183
+ }
184
+ function isTextualContentBlock(block) {
185
+ if (block === null || typeof block !== "object") return false;
186
+ const rec = block;
187
+ if (typeof rec["text"] === "string") return true;
188
+ if (rec["type"] === "resource_link") return true;
189
+ const resource = rec["resource"];
190
+ return resource !== null && typeof resource === "object" && typeof resource["text"] === "string";
191
+ }
192
+ function withPreservedBlocks(output, blocks) {
193
+ if (output.hookType !== "rewriteOutput" || blocks.length === 0) return output;
194
+ return { ...output, updatedBlocks: [{ type: "text", text: output.updatedOutput }, ...blocks] };
195
+ }
196
+ function dropsResultRewrite() {
197
+ return detectHarness() === "vscode";
198
+ }
199
+ function passOutput() {
200
+ return { hookType: "pass" };
201
+ }
202
+ function denyOutput(message) {
203
+ return { hookType: "deny", message: `[tg] ${neutralizeOutsideFences(message)}` };
204
+ }
205
+ function contextOutput(context, correlators) {
206
+ return correlators === void 0 ? { hookType: "context", context } : { hookType: "context", context, correlators };
207
+ }
208
+ function emitRewrite(updatedOutput, detail, savings, redaction = "count-here") {
209
+ if (dropsResultRewrite()) return passOutput();
210
+ if (redaction === "count-here") {
211
+ const count = countRedactionPlaceholders(updatedOutput);
212
+ if (count > 0) recordStat("secret_redacted", 0, count, void 0, detail);
213
+ }
214
+ if (savings !== void 0) {
215
+ const bytesSaved = savings.originalBytes - Buffer.byteLength(updatedOutput, "utf-8");
216
+ const credited = Math.max(0, bytesSaved);
217
+ recordStat(savings.kind, credited, savedTokensFromBytes(credited), void 0, savings.detail);
218
+ }
219
+ return { hookType: "rewriteOutput", updatedOutput };
220
+ }
221
+ function emitRewriteIfChanged(original, emitted, detail) {
222
+ if (emitted === original) return passOutput();
223
+ return emitRewrite(emitted, detail);
224
+ }
225
+ function emitRewriteWithContext(updatedOutput, context, detail, savings) {
226
+ const out = emitRewrite(updatedOutput, detail, { ...savings, originalBytes: savings.originalBytes - Buffer.byteLength(context, "utf-8") });
227
+ return out.hookType === "rewriteOutput" ? { ...out, context } : out;
228
+ }
229
+ function countNonEmptyLines(text) {
230
+ return text.split(/\r\n|\r|\n/).filter((line) => line.length > 0).length;
231
+ }
232
+ function estimateResultCount(text) {
233
+ const firstLine = text.split(/\r\n|\r|\n/).find((line) => line.trim().length > 0);
234
+ if (firstLine !== void 0) {
235
+ const trimmed = firstLine.trim();
236
+ if (/^No (?:files|matches) found\.?$/i.test(trimmed)) return 0;
237
+ const found = /^Found (\d+) (?:files?|matches?)\.?$/i.exec(trimmed);
238
+ if (found) return Number.parseInt(found[1], 10);
239
+ }
240
+ return countNonEmptyLines(text);
241
+ }
242
+ var RESULT_COUNT_KEYS = ["numFiles", "numLines", "numMatches"];
243
+ function structuredResultCount(raw) {
244
+ const response = raw["tool_response"];
245
+ if (response === null || typeof response !== "object") return null;
246
+ const counts = RESULT_COUNT_KEYS.map((k) => response[k]).filter((v) => typeof v === "number");
247
+ return counts.length > 0 ? Math.max(...counts) : null;
248
+ }
249
+ function makeDedupHintHandlers(opts) {
250
+ const post = (event) => {
251
+ try {
252
+ if (getToolName(event) !== opts.toolName) return passOutput();
253
+ const signature = opts.buildSignature(getToolInput(event));
254
+ if (signature === null) return passOutput();
255
+ opts.recordQuery(signature, structuredResultCount(event.raw) ?? estimateResultCount(extractToolResponseField(event.raw, OUTPUT_FIRST_TOOL_RESPONSE_KEYS)));
256
+ return passOutput();
257
+ } catch {
258
+ return passOutput();
259
+ }
260
+ };
261
+ const pre = (event) => {
262
+ try {
263
+ if (getToolName(event) !== opts.toolName) return passOutput();
264
+ const toolInput = getToolInput(event);
265
+ const signature = opts.buildSignature(toolInput);
266
+ if (signature === null) return passOutput();
267
+ const priorCount = opts.getMatchCount(signature);
268
+ if (priorCount === null) return passOutput();
269
+ if (priorCount < loadConfig().hints[opts.minMatchesConfigKey]) return passOutput();
270
+ recordStat(opts.statName, 0, 0);
271
+ const pattern = displaySafeText(typeof toolInput["pattern"] === "string" ? toolInput["pattern"] : "");
272
+ return contextOutput(
273
+ "Note: an identical " + opts.toolName + " for " + echoedValue(pattern) + " already ran this session and returned " + priorCount + (priorCount === 1 ? " match" : " matches") + ". If that result already answers this, you can skip re-running it."
274
+ );
275
+ } catch {
276
+ return passOutput();
277
+ }
278
+ };
279
+ return { post, pre };
280
+ }
281
+
32
282
  // src/hooks_cli.ts
33
283
  init_define_import_meta_env();
34
284
 
@@ -152,8 +402,7 @@ function readCopilotMcpTools(dir = copilotCliMcpToolsDir(), userRoot = copilotCl
152
402
  definitionBytes,
153
403
  estimatedTokens: estimateTokensFromLength(definitionBytes),
154
404
  updatedAt,
155
- // `tools` is an unchecked cast off a JSON array, so every element is
156
- // treated as untrusted here rather than trusted to match CachedTool.
405
+ // `tools` is an unchecked cast off a JSON array, so every element is treated as untrusted here rather than trusted to match CachedTool.
157
406
  toolNames: tools.map((t) => t?.name).filter((n) => typeof n === "string" && n !== "")
158
407
  };
159
408
  const existing = newest.get(serverName);
@@ -281,7 +530,8 @@ function normalizeToolNameWithMap(toolName, nameMap) {
281
530
  }
282
531
  var COPILOT_CLI_INPUT_KEY_MAP = {
283
532
  Read: { path: "file_path" },
284
- Write: { path: "file_path" },
533
+ // CAPTURE: the real Copilot CLI `create` arguments {path, file_text} in a session log (events.jsonl, tool.execution_start, toolName "create"); the `edit` entry below is FORMAT-DERIVED from the tool description in a Copilot CLI 1.0.88 session log.
534
+ Write: { path: "file_path", file_text: "content" },
285
535
  Edit: { path: "file_path", old_str: "old_string", new_str: "new_string" },
286
536
  BashOutput: { shellId: "bash_id" }
287
537
  };
@@ -660,251 +910,8 @@ function normalizePayload(payload, harness = "claude") {
660
910
  return result;
661
911
  }
662
912
 
663
- // src/hooks_common.ts
664
- init_define_import_meta_env();
665
- function getToolName(event) {
666
- return event.toolName;
667
- }
668
- function getToolInput(event) {
669
- return event.toolInput;
670
- }
671
- function getFilePath(event) {
672
- const value = event.toolInput["file_path"];
673
- if (typeof value === "string" && value !== "") return resolveEventPath(event, value);
674
- const notebookValue = event.toolInput["notebook_path"];
675
- return typeof notebookValue === "string" && notebookValue !== "" ? resolveEventPath(event, notebookValue) : void 0;
676
- }
677
- function resolveEventPath(event, file) {
678
- return resolveToolPath(file, getCwd(event));
679
- }
680
- function getFilePaths(event) {
681
- const out = [];
682
- const list = event.toolInput["file_paths"];
683
- if (Array.isArray(list)) {
684
- for (const entry of list) {
685
- if (typeof entry !== "string" || entry === "") continue;
686
- const resolved = resolveEventPath(event, entry);
687
- if (!out.includes(resolved)) out.push(resolved);
688
- }
689
- }
690
- const single = getFilePath(event);
691
- if (single !== void 0 && !out.includes(single)) out.push(single);
692
- return out;
693
- }
694
- function getCwd(event) {
695
- const value = event.raw && typeof event.raw === "object" ? event.raw["cwd"] : void 0;
696
- return typeof value === "string" && value !== "" ? value : void 0;
697
- }
698
- function getTranscriptPath(event) {
699
- const value = event.raw && typeof event.raw === "object" ? event.raw["transcript_path"] : void 0;
700
- return typeof value === "string" && value !== "" ? value : void 0;
701
- }
702
- function extractToolResponseField(raw, keys) {
703
- const resp = raw["tool_response"];
704
- if (typeof resp === "string") return resp;
705
- if (resp !== null && typeof resp === "object") {
706
- const r = resp;
707
- const path3 = resolveToolResponseFieldPath(r, keys);
708
- if (path3 !== null) return readAtPath(r, path3);
709
- }
710
- return "";
711
- }
712
- var NESTED_TOOL_RESPONSE_PATHS = [["file", "content"]];
713
- function readAtPath(resp, path3) {
714
- let cur = resp;
715
- for (const seg of path3) {
716
- if (cur === null || typeof cur !== "object") return "";
717
- cur = cur[seg];
718
- }
719
- return typeof cur === "string" ? cur : "";
720
- }
721
- function resolveToolResponseFieldPath(resp, keys) {
722
- for (const key of keys) {
723
- if (typeof resp[key] === "string" && resp[key] !== "") return [key];
724
- }
725
- for (const path3 of NESTED_TOOL_RESPONSE_PATHS) {
726
- if (readAtPath(resp, path3) !== "") return path3;
727
- }
728
- return null;
729
- }
730
- function replaceToolResponseField(resp, keys, newText) {
731
- const path3 = resolveToolResponseFieldPath(resp, keys);
732
- if (path3 === null) return null;
733
- const root = { ...resp };
734
- let cur = root;
735
- for (let i = 0; i < path3.length - 1; i++) {
736
- const seg = path3[i];
737
- const child = cur[seg];
738
- if (child === null || typeof child !== "object") return null;
739
- const cloned = { ...child };
740
- cur[seg] = cloned;
741
- cur = cloned;
742
- }
743
- cur[path3[path3.length - 1]] = newText;
744
- return root;
745
- }
746
- var OUTPUT_FIRST_TOOL_RESPONSE_KEYS = ["output", "content", "text", "body", "stdout", "stderr"];
747
- var BODY_FIRST_TOOL_RESPONSE_KEYS = ["output", "body", "text", "content", "result"];
748
- function isMcpErrorResponse(raw) {
749
- const tr = raw["tool_response"];
750
- if (!tr || typeof tr !== "object") return false;
751
- return tr["isError"] === true;
752
- }
753
- var MCP_CONTENT_BLOCK_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "resource", "resource_link"]);
754
- function blocksToText(blocks) {
755
- if (!Array.isArray(blocks)) return null;
756
- const parts = [];
757
- let recognised = false;
758
- for (const block of blocks) {
759
- if (!block || typeof block !== "object") continue;
760
- const rec = block;
761
- const type = rec["type"];
762
- if (typeof type === "string" && MCP_CONTENT_BLOCK_TYPES.has(type)) recognised = true;
763
- if (typeof rec["text"] === "string") {
764
- parts.push(rec["text"]);
765
- continue;
766
- }
767
- const resource = rec["resource"];
768
- if (resource !== null && typeof resource === "object") {
769
- const nested = resource["text"];
770
- if (typeof nested === "string") parts.push(nested);
771
- continue;
772
- }
773
- if (rec["type"] === "resource_link") {
774
- const link = ["name", "uri", "description"].map((k) => rec[k]).filter((v) => typeof v === "string" && v !== "");
775
- if (link.length > 0) parts.push(link.join(" "));
776
- }
777
- }
778
- if (parts.length > 0) return parts.join("\n");
779
- return recognised ? "" : null;
780
- }
781
- function extractToolResultText(raw) {
782
- const tr = raw["tool_response"];
783
- if (typeof tr === "string") return tr;
784
- if (!tr || typeof tr !== "object") return "";
785
- const bare = blocksToText(tr);
786
- if (bare !== null) return bare;
787
- const resp = tr;
788
- const content = resp["content"];
789
- const joined = blocksToText(content);
790
- if (joined !== null) return joined;
791
- for (const key of ["output", "text", "body"]) {
792
- if (typeof resp[key] === "string") return resp[key];
793
- }
794
- if (typeof content === "string") return content;
795
- try {
796
- return JSON.stringify(resp);
797
- } catch {
798
- return "";
799
- }
800
- }
801
- function asContentBlocks(value) {
802
- if (!Array.isArray(value)) return null;
803
- const blocks = value.filter((b) => b !== null && typeof b === "object");
804
- const typed = blocks.some((b) => typeof b["type"] === "string" && MCP_CONTENT_BLOCK_TYPES.has(b["type"]));
805
- return typed ? blocks : null;
806
- }
807
- function mcpContentBlocks(raw) {
808
- const tr = raw["tool_response"];
809
- if (tr === null || typeof tr !== "object") return null;
810
- return asContentBlocks(tr) ?? asContentBlocks(tr["content"]);
811
- }
812
- function isTextualContentBlock(block) {
813
- if (block === null || typeof block !== "object") return false;
814
- const rec = block;
815
- if (typeof rec["text"] === "string") return true;
816
- if (rec["type"] === "resource_link") return true;
817
- const resource = rec["resource"];
818
- return resource !== null && typeof resource === "object" && typeof resource["text"] === "string";
819
- }
820
- function withPreservedBlocks(output, blocks) {
821
- if (output.hookType !== "rewriteOutput" || blocks.length === 0) return output;
822
- return { ...output, updatedBlocks: [{ type: "text", text: output.updatedOutput }, ...blocks] };
823
- }
824
- function passOutput() {
825
- return { hookType: "pass" };
826
- }
827
- function denyOutput(message) {
828
- return { hookType: "deny", message: `[tg] ${neutralizeOutsideFences(message)}` };
829
- }
830
- function contextOutput(context, correlators) {
831
- return correlators === void 0 ? { hookType: "context", context } : { hookType: "context", context, correlators };
832
- }
833
- function emitRewrite(updatedOutput, detail, savings, redaction = "count-here") {
834
- if (detectHarness() === "vscode") return passOutput();
835
- if (redaction === "count-here") {
836
- const count = countRedactionPlaceholders(updatedOutput);
837
- if (count > 0) recordStat("secret_redacted", 0, count, void 0, detail);
838
- }
839
- if (savings !== void 0) {
840
- const bytesSaved = savings.originalBytes - Buffer.byteLength(updatedOutput, "utf-8");
841
- const credited = Math.max(0, bytesSaved);
842
- recordStat(savings.kind, credited, savedTokensFromBytes(credited), void 0, savings.detail);
843
- }
844
- return { hookType: "rewriteOutput", updatedOutput };
845
- }
846
- function emitRewriteIfChanged(original, emitted, detail) {
847
- if (emitted === original) return passOutput();
848
- return emitRewrite(emitted, detail);
849
- }
850
- function emitRewriteWithContext(updatedOutput, context, detail, savings) {
851
- const out = emitRewrite(updatedOutput, detail, { ...savings, originalBytes: savings.originalBytes - Buffer.byteLength(context, "utf-8") });
852
- return out.hookType === "rewriteOutput" ? { ...out, context } : out;
853
- }
854
- function countNonEmptyLines(text) {
855
- return text.split(/\r\n|\r|\n/).filter((line) => line.length > 0).length;
856
- }
857
- function estimateResultCount(text) {
858
- const firstLine = text.split(/\r\n|\r|\n/).find((line) => line.trim().length > 0);
859
- if (firstLine !== void 0) {
860
- const trimmed = firstLine.trim();
861
- if (/^No (?:files|matches) found\.?$/i.test(trimmed)) return 0;
862
- const found = /^Found (\d+) (?:files?|matches?)\.?$/i.exec(trimmed);
863
- if (found) return Number.parseInt(found[1], 10);
864
- }
865
- return countNonEmptyLines(text);
866
- }
867
- var RESULT_COUNT_KEYS = ["numFiles", "numLines", "numMatches"];
868
- function structuredResultCount(raw) {
869
- const response = raw["tool_response"];
870
- if (response === null || typeof response !== "object") return null;
871
- const counts = RESULT_COUNT_KEYS.map((k) => response[k]).filter((v) => typeof v === "number");
872
- return counts.length > 0 ? Math.max(...counts) : null;
873
- }
874
- function makeDedupHintHandlers(opts) {
875
- const post = (event) => {
876
- try {
877
- if (getToolName(event) !== opts.toolName) return passOutput();
878
- const signature = opts.buildSignature(getToolInput(event));
879
- if (signature === null) return passOutput();
880
- opts.recordQuery(signature, structuredResultCount(event.raw) ?? estimateResultCount(extractToolResponseField(event.raw, OUTPUT_FIRST_TOOL_RESPONSE_KEYS)));
881
- return passOutput();
882
- } catch {
883
- return passOutput();
884
- }
885
- };
886
- const pre = (event) => {
887
- try {
888
- if (getToolName(event) !== opts.toolName) return passOutput();
889
- const toolInput = getToolInput(event);
890
- const signature = opts.buildSignature(toolInput);
891
- if (signature === null) return passOutput();
892
- const priorCount = opts.getMatchCount(signature);
893
- if (priorCount === null) return passOutput();
894
- if (priorCount < loadConfig().hints[opts.minMatchesConfigKey]) return passOutput();
895
- recordStat(opts.statName, 0, 0);
896
- const pattern = displaySafeText(typeof toolInput["pattern"] === "string" ? toolInput["pattern"] : "");
897
- return contextOutput(
898
- "Note: an identical " + opts.toolName + ' for "' + pattern + '" already ran this session and returned ' + priorCount + (priorCount === 1 ? " match" : " matches") + ". If that result already answers this, you can skip re-running it."
899
- );
900
- } catch {
901
- return passOutput();
902
- }
903
- };
904
- return { post, pre };
905
- }
906
-
907
913
  export {
914
+ foldToolName,
908
915
  getToolName,
909
916
  getToolInput,
910
917
  getFilePath,
@@ -922,6 +929,7 @@ export {
922
929
  mcpContentBlocks,
923
930
  isTextualContentBlock,
924
931
  withPreservedBlocks,
932
+ dropsResultRewrite,
925
933
  passOutput,
926
934
  denyOutput,
927
935
  contextOutput,
@@ -935,7 +943,6 @@ export {
935
943
  copilotCliMcpToolsDir,
936
944
  readCopilotMcpTools,
937
945
  COPILOT_CLI_TOOL_NAME_MAP,
938
- foldToolName,
939
946
  GEMINI_TOOL_NAME_MAP,
940
947
  VSCODE_TOOL_NAME_KEY,
941
948
  vscodeNativeToolInput,