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.
Files changed (197) hide show
  1. package/README.md +53 -42
  2. package/SECURITY.md +37 -11
  3. package/THIRD_PARTY_NOTICES.md +41 -4
  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/ort-wasm-simd-threaded.mjs +59 -0
  9. package/dist/{token-goat-chunk-SE6E4BKJ.mjs → token-goat-chunk-25TRAWET.mjs} +23 -6
  10. package/dist/token-goat-chunk-2KXO6V2B.mjs +203 -0
  11. package/dist/{token-goat-chunk-UXSXQQIY.mjs → token-goat-chunk-2M7E4PF7.mjs} +43 -14
  12. package/dist/token-goat-chunk-2UPZGKKY.mjs +188 -0
  13. package/dist/token-goat-chunk-2WLPWKHV.mjs +135 -0
  14. package/dist/token-goat-chunk-2XBMMDBD.mjs +126 -0
  15. package/dist/token-goat-chunk-32ZOY4N5.mjs +23 -0
  16. package/dist/token-goat-chunk-3EZRNKTK.mjs +188 -0
  17. package/dist/token-goat-chunk-4ADZHI7J.mjs +63 -0
  18. package/dist/token-goat-chunk-4GBVPH3D.mjs +242 -0
  19. package/dist/{token-goat-chunk-2WOUYWLM.mjs → token-goat-chunk-4GILLLWY.mjs} +34 -7
  20. package/dist/token-goat-chunk-4NAPX7BA.mjs +90 -0
  21. package/dist/{token-goat-chunk-NMBWLRHW.mjs → token-goat-chunk-4SC7UJYV.mjs} +9981 -11563
  22. package/dist/token-goat-chunk-4SMRO4TO.mjs +366 -0
  23. package/dist/{token-goat-chunk-O6I2XU4P.mjs → token-goat-chunk-4ZBFWLXF.mjs} +310 -441
  24. package/dist/token-goat-chunk-57BIAXJL.mjs +286 -0
  25. package/dist/token-goat-chunk-5AC66HNP.mjs +115 -0
  26. package/dist/token-goat-chunk-5IMLKSOP.mjs +145 -0
  27. package/dist/token-goat-chunk-5RG5SBL6.mjs +221 -0
  28. package/dist/{token-goat-chunk-RRNZMM3A.mjs → token-goat-chunk-5Y6ZYL6U.mjs} +21 -2
  29. package/dist/token-goat-chunk-646E6U44.mjs +398 -0
  30. package/dist/token-goat-chunk-65N4RHP4.mjs +33 -0
  31. package/dist/{token-goat-chunk-6AK46ZT7.mjs → token-goat-chunk-6DG6HWP3.mjs} +13 -3
  32. package/dist/token-goat-chunk-6ENQSNRZ.mjs +573 -0
  33. package/dist/token-goat-chunk-6ZY4GNF2.mjs +91 -0
  34. package/dist/{token-goat-chunk-E5TK5DNO.mjs → token-goat-chunk-76FGDLRO.mjs} +574 -340
  35. package/dist/{token-goat-chunk-TGOXNAHW.mjs → token-goat-chunk-7EZTZOMC.mjs} +780 -767
  36. package/dist/token-goat-chunk-7MAOA6X4.mjs +3647 -0
  37. package/dist/token-goat-chunk-7R2ZVVAX.mjs +218 -0
  38. package/dist/{token-goat-chunk-TCQANXYC.mjs → token-goat-chunk-AM5V6GSX.mjs} +18 -2
  39. package/dist/token-goat-chunk-AUNGYYQX.mjs +184 -0
  40. package/dist/token-goat-chunk-AUQYRMMH.mjs +2985 -0
  41. package/dist/token-goat-chunk-B3PEKBYG.mjs +128 -0
  42. package/dist/{token-goat-chunk-KOPIR3KZ.mjs → token-goat-chunk-BA4HI6BW.mjs} +1910 -165
  43. package/dist/{token-goat-chunk-52NSDWYY.mjs → token-goat-chunk-BFCWY73P.mjs} +58 -20
  44. package/dist/token-goat-chunk-BPGCUMR7.mjs +30 -0
  45. package/dist/token-goat-chunk-BWGFUZZE.mjs +25 -0
  46. package/dist/token-goat-chunk-C75NA7PL.mjs +322 -0
  47. package/dist/token-goat-chunk-CBIQ7WTD.mjs +87 -0
  48. package/dist/token-goat-chunk-CETM74KC.mjs +307 -0
  49. package/dist/token-goat-chunk-CIMQ2BB3.mjs +233 -0
  50. package/dist/{token-goat-chunk-DNSPXQXQ.mjs → token-goat-chunk-CJLS3CDL.mjs} +70 -18
  51. package/dist/{token-goat-chunk-MELOKFDJ.mjs → token-goat-chunk-CO3UYX6G.mjs} +7 -1
  52. package/dist/token-goat-chunk-COPNXRJM.mjs +154 -0
  53. package/dist/token-goat-chunk-CSJ5L3NL.mjs +479 -0
  54. package/dist/token-goat-chunk-CVCEVUGK.mjs +315 -0
  55. package/dist/token-goat-chunk-CXHOFN7R.mjs +371 -0
  56. package/dist/token-goat-chunk-D735C4QM.mjs +603 -0
  57. package/dist/{token-goat-chunk-E4ZOJIZK.mjs → token-goat-chunk-DGS2LVNA.mjs} +70 -160
  58. package/dist/{token-goat-chunk-L7H3U27L.mjs → token-goat-chunk-DOWRSMWO.mjs} +1 -1
  59. package/dist/token-goat-chunk-E45INMY3.mjs +71 -0
  60. package/dist/token-goat-chunk-EC5F37F4.mjs +244 -0
  61. package/dist/{token-goat-chunk-XTQAOTSO.mjs → token-goat-chunk-EDBDRVH5.mjs} +4 -1
  62. package/dist/token-goat-chunk-EELTBKDM.mjs +613 -0
  63. package/dist/token-goat-chunk-EVMZJ27Z.mjs +147 -0
  64. package/dist/token-goat-chunk-EXKGNHEG.mjs +2096 -0
  65. package/dist/{token-goat-chunk-YOOVFPTP.mjs → token-goat-chunk-F4HYL64R.mjs} +12 -2
  66. package/dist/token-goat-chunk-F6PAUIEK.mjs +624 -0
  67. package/dist/token-goat-chunk-FDSREWLX.mjs +692 -0
  68. package/dist/{token-goat-chunk-NMTKNYGF.mjs → token-goat-chunk-FNFBKLRD.mjs} +74 -9
  69. package/dist/token-goat-chunk-G5PJ7AGM.mjs +36 -0
  70. package/dist/token-goat-chunk-GGGG7RWB.mjs +236 -0
  71. package/dist/{token-goat-chunk-TDUT2CL6.mjs → token-goat-chunk-GL3ETKSC.mjs} +276 -19
  72. package/dist/{token-goat-chunk-7CPMDFGB.mjs → token-goat-chunk-GVB2MUST.mjs} +265 -1567
  73. package/dist/token-goat-chunk-GWFLAUMQ.mjs +307 -0
  74. package/dist/token-goat-chunk-HAVAOB3S.mjs +87 -0
  75. package/dist/token-goat-chunk-HLPW63A7.mjs +48 -0
  76. package/dist/token-goat-chunk-HU4TORC5.mjs +1377 -0
  77. package/dist/token-goat-chunk-I7VKZZAW.mjs +35 -0
  78. package/dist/token-goat-chunk-IA6XSPE3.mjs +218 -0
  79. package/dist/token-goat-chunk-IAGXMHIK.mjs +863 -0
  80. package/dist/{token-goat-chunk-435UQTKD.mjs → token-goat-chunk-IK2DRMFX.mjs} +129 -74
  81. package/dist/{token-goat-chunk-ZER6EAXZ.mjs → token-goat-chunk-INNPTRUX.mjs} +2954 -2783
  82. package/dist/token-goat-chunk-JJ5BX4F4.mjs +129 -0
  83. package/dist/token-goat-chunk-JVFSHVFJ.mjs +129 -0
  84. package/dist/token-goat-chunk-KGEFFSHD.mjs +50 -0
  85. package/dist/token-goat-chunk-KKUFXAPD.mjs +25 -0
  86. package/dist/token-goat-chunk-KQBLRPBN.mjs +433 -0
  87. package/dist/token-goat-chunk-LCNQ2CNN.mjs +497 -0
  88. package/dist/token-goat-chunk-M3LFJDPU.mjs +58 -0
  89. package/dist/token-goat-chunk-M52KPT3C.mjs +87 -0
  90. package/dist/token-goat-chunk-MBEG42H7.mjs +150 -0
  91. package/dist/{token-goat-chunk-EVC4TOLE.mjs → token-goat-chunk-METECDOH.mjs} +3 -12
  92. package/dist/{token-goat-chunk-2AWQ2R5X.mjs → token-goat-chunk-MHX7XCC3.mjs} +3 -2
  93. package/dist/token-goat-chunk-MNWKPRAL.mjs +13 -0
  94. package/dist/token-goat-chunk-N5LSOVSU.mjs +137 -0
  95. package/dist/{token-goat-chunk-DPNLUJWB.mjs → token-goat-chunk-N5MMR2IW.mjs} +30 -8
  96. package/dist/token-goat-chunk-N7B3JQ2C.mjs +160 -0
  97. package/dist/{token-goat-chunk-VMFWNHGR.mjs → token-goat-chunk-NISNMD7T.mjs} +2545 -2953
  98. package/dist/token-goat-chunk-NMD42SFQ.mjs +434 -0
  99. package/dist/token-goat-chunk-NOSS5VWY.mjs +174 -0
  100. package/dist/token-goat-chunk-NSNSPPBG.mjs +69 -0
  101. package/dist/token-goat-chunk-OBOFIHKN.mjs +38 -0
  102. package/dist/token-goat-chunk-OBRFJ5O5.mjs +76 -0
  103. package/dist/token-goat-chunk-ODBT2USM.mjs +800 -0
  104. package/dist/token-goat-chunk-OS5EM5PP.mjs +107 -0
  105. package/dist/token-goat-chunk-OUKDTVNU.mjs +1178 -0
  106. package/dist/token-goat-chunk-OXFMP75N.mjs +566 -0
  107. package/dist/{token-goat-chunk-ASLWOQ3I.mjs → token-goat-chunk-OYIYKDDT.mjs} +2 -1
  108. package/dist/{token-goat-chunk-67BNIKKO.mjs → token-goat-chunk-P6HQSWQ3.mjs} +55 -47
  109. package/dist/token-goat-chunk-P6VGNTQT.mjs +71 -0
  110. package/dist/token-goat-chunk-PFWIMH2E.mjs +261 -0
  111. package/dist/token-goat-chunk-PJZXIS3G.mjs +39 -0
  112. package/dist/token-goat-chunk-PUO5INXP.mjs +606 -0
  113. package/dist/token-goat-chunk-PX5PQWTY.mjs +462 -0
  114. package/dist/token-goat-chunk-Q5QDBC6O.mjs +111 -0
  115. package/dist/token-goat-chunk-QFNQXSDT.mjs +40 -0
  116. package/dist/token-goat-chunk-QH7YVYOY.mjs +3957 -0
  117. package/dist/token-goat-chunk-QLMUHEPB.mjs +43 -0
  118. package/dist/{token-goat-chunk-PYSUADX4.mjs → token-goat-chunk-QQOJIHL3.mjs} +50 -14
  119. package/dist/token-goat-chunk-QQTWJY2O.mjs +85 -0
  120. package/dist/token-goat-chunk-QYHO5CPH.mjs +93 -0
  121. package/dist/token-goat-chunk-RELAVWAD.mjs +27 -0
  122. package/dist/token-goat-chunk-RSLPOBKQ.mjs +339 -0
  123. package/dist/token-goat-chunk-SAMFDIS2.mjs +712 -0
  124. package/dist/token-goat-chunk-SDELXLDM.mjs +48 -0
  125. package/dist/{token-goat-chunk-PGTH2U4C.mjs → token-goat-chunk-SOAFZNNZ.mjs} +164 -40
  126. package/dist/{token-goat-chunk-G23DWHV4.mjs → token-goat-chunk-SRTHT7KV.mjs} +33 -15
  127. package/dist/token-goat-chunk-T5P5ACNQ.mjs +212 -0
  128. package/dist/token-goat-chunk-T5YGG4V3.mjs +45 -0
  129. package/dist/token-goat-chunk-TAUZ4OFS.mjs +110 -0
  130. package/dist/token-goat-chunk-TM6MC754.mjs +40 -0
  131. package/dist/token-goat-chunk-TWUKBOMP.mjs +72 -0
  132. package/dist/token-goat-chunk-U2KSB4SG.mjs +56 -0
  133. package/dist/token-goat-chunk-U4WHMG6Y.mjs +898 -0
  134. package/dist/token-goat-chunk-UA5V6P3P.mjs +122 -0
  135. package/dist/token-goat-chunk-UGJHGR5A.mjs +52 -0
  136. package/dist/{token-goat-chunk-RQGGMPCR.mjs → token-goat-chunk-UOUDVA5U.mjs} +76 -16
  137. package/dist/{token-goat-chunk-HNFZZHFW.mjs → token-goat-chunk-URRJ33GR.mjs} +22 -4
  138. package/dist/token-goat-chunk-UZOROKIS.mjs +165 -0
  139. package/dist/token-goat-chunk-VIHGGGEI.mjs +4234 -0
  140. package/dist/token-goat-chunk-VTJLAA7P.mjs +21 -0
  141. package/dist/token-goat-chunk-VWDXLT4F.mjs +678 -0
  142. package/dist/token-goat-chunk-VWZA2H4P.mjs +368 -0
  143. package/dist/{token-goat-chunk-QO3LXVVR.mjs → token-goat-chunk-VXEXMJDL.mjs} +2964 -3153
  144. package/dist/token-goat-chunk-WBA5SKT4.mjs +547 -0
  145. package/dist/{token-goat-chunk-ONXH6NZ5.mjs → token-goat-chunk-WDH44VAU.mjs} +19 -22
  146. package/dist/token-goat-chunk-X2SUP3EI.mjs +107 -0
  147. package/dist/token-goat-chunk-X3BELZSJ.mjs +125 -0
  148. package/dist/{token-goat-chunk-RLP6J7WR.mjs → token-goat-chunk-XLRBNZCC.mjs} +40 -21
  149. package/dist/{token-goat-chunk-S4VSXURL.mjs → token-goat-chunk-XRKUX6CM.mjs} +4 -0
  150. package/dist/token-goat-chunk-XX6O25RN.mjs +82 -0
  151. package/dist/token-goat-chunk-XZSUHBVS.mjs +65 -0
  152. package/dist/token-goat-chunk-Y2ZTQOCL.mjs +35 -0
  153. package/dist/{token-goat-chunk-UA5BKWWQ.mjs → token-goat-chunk-YB4VMGK2.mjs} +15 -4
  154. package/dist/token-goat-chunk-YBIIY3HR.mjs +51 -0
  155. package/dist/{token-goat-chunk-PKRWMHVP.mjs → token-goat-chunk-YHVDKQBR.mjs} +389 -221
  156. package/dist/token-goat-chunk-YJB5XLWI.mjs +26 -0
  157. package/dist/{token-goat-chunk-PQ53BSCF.mjs → token-goat-chunk-YKB6AQG3.mjs} +53 -31
  158. package/dist/token-goat-chunk-YMTG2YA5.mjs +35 -0
  159. package/dist/token-goat-chunk-YPBZYQRV.mjs +40 -0
  160. package/dist/{token-goat-chunk-HUYUHODZ.mjs → token-goat-chunk-YY6AVUFL.mjs} +13246 -12247
  161. package/dist/token-goat-chunk-Z7N5OMMP.mjs +98 -0
  162. package/dist/{token-goat-chunk-BGHSSJUA.mjs → token-goat-chunk-ZFOBKUWH.mjs} +1 -1
  163. package/dist/token-goat-chunk-ZMBL6UVV.mjs +110 -0
  164. package/dist/token-goat-chunk-ZNMNUPAZ.mjs +938 -0
  165. package/dist/token-goat-hook-client.cjs +87 -23
  166. package/dist/token-goat-hook-client.mjs +3 -3
  167. package/dist/token-goat-hook.mjs +76 -31
  168. package/dist/token-goat.core.mjs +6 -6
  169. package/docs/C4_RUNTIME_ARCHITECTURE.md +2 -2
  170. package/docs/cli.md +113 -60
  171. package/docs/install.md +63 -20
  172. package/docs/security.md +10 -8
  173. package/package.json +18 -7
  174. package/scripts/verify-native-dist.mjs +386 -0
  175. package/dist/token-goat-chunk-2NNUA2LR.mjs +0 -143
  176. package/dist/token-goat-chunk-44BM7DDQ.mjs +0 -294
  177. package/dist/token-goat-chunk-BGYOZ6DO.mjs +0 -24
  178. package/dist/token-goat-chunk-C5YPNZKQ.mjs +0 -318
  179. package/dist/token-goat-chunk-CIQ2FTY3.mjs +0 -1990
  180. package/dist/token-goat-chunk-D4ETHJD6.mjs +0 -246
  181. package/dist/token-goat-chunk-DNRPXHYH.mjs +0 -1062
  182. package/dist/token-goat-chunk-EUSDXRXU.mjs +0 -1429
  183. package/dist/token-goat-chunk-FTP4U4QA.mjs +0 -64
  184. package/dist/token-goat-chunk-G7IWXCFF.mjs +0 -456
  185. package/dist/token-goat-chunk-GLXRTTLE.mjs +0 -36
  186. package/dist/token-goat-chunk-H5J3C56Q.mjs +0 -1511
  187. package/dist/token-goat-chunk-IVWI2OCK.mjs +0 -368
  188. package/dist/token-goat-chunk-JTKCQMQA.mjs +0 -418
  189. package/dist/token-goat-chunk-LZNBQTDK.mjs +0 -26
  190. package/dist/token-goat-chunk-ORNFMIER.mjs +0 -295
  191. package/dist/token-goat-chunk-RTMVLHWX.mjs +0 -7113
  192. package/dist/token-goat-chunk-VQ6F6T7X.mjs +0 -36
  193. package/dist/token-goat-chunk-VZQEWRVH.mjs +0 -312
  194. package/dist/token-goat-chunk-XYWPOSCN.mjs +0 -807
  195. package/dist/token-goat-chunk-YAGLESS3.mjs +0 -23
  196. package/dist/token-goat-chunk-YKSRAWUU.mjs +0 -33
  197. package/dist/token-goat-chunk-Z6KBMOBI.mjs +0 -53
@@ -1,5 +1,12 @@
1
1
  import { createRequire as __cjsRequire } from 'node:module';
2
2
  const require = __cjsRequire(import.meta.url);
3
+ import {
4
+ KNOWN_HARNESS_NAMES
5
+ } from "./token-goat-chunk-QYHO5CPH.mjs";
6
+ import {
7
+ findProject,
8
+ shortFingerprint
9
+ } from "./token-goat-chunk-4GBVPH3D.mjs";
3
10
  import {
4
11
  registerReset
5
12
  } from "./token-goat-chunk-YZAAZU2S.mjs";
@@ -14,333 +21,23 @@ import {
14
21
  import {
15
22
  atomicWriteText,
16
23
  decodeSource,
17
- extractErrorMessage,
18
- runGit
19
- } from "./token-goat-chunk-XYWPOSCN.mjs";
20
- import {
21
- canonicalize,
22
- foldPath
23
- } from "./token-goat-chunk-TCQANXYC.mjs";
24
+ extractErrorMessage
25
+ } from "./token-goat-chunk-HU4TORC5.mjs";
24
26
  import {
25
- normalizeDarwinSystemAlias
26
- } from "./token-goat-chunk-NMTKNYGF.mjs";
27
+ echoedValue
28
+ } from "./token-goat-chunk-GGGG7RWB.mjs";
27
29
  import {
28
- ENV_KEYS,
29
30
  configPath,
30
31
  projectConfigPath
31
- } from "./token-goat-chunk-MELOKFDJ.mjs";
32
+ } from "./token-goat-chunk-CO3UYX6G.mjs";
32
33
  import {
33
34
  init_define_import_meta_env
34
35
  } from "./token-goat-chunk-A37V4PBF.mjs";
35
36
 
36
- // src/bridges/registry.ts
37
- init_define_import_meta_env();
38
- var KNOWN_HARNESS_NAMES = /* @__PURE__ */ new Set([
39
- "claudecode",
40
- "codex",
41
- "opencode",
42
- "gemini",
43
- "hermes",
44
- "openclaw",
45
- "pi",
46
- "copilot_cli",
47
- "grok",
48
- "qwen",
49
- "kimi",
50
- "vscode",
51
- "visualstudio",
52
- "generic"
53
- ]);
54
- var relaySeededSessionIdValue;
55
- function setRelaySeededSessionId(id) {
56
- relaySeededSessionIdValue = id;
57
- }
58
- function relaySeededSessionId() {
59
- return relaySeededSessionIdValue;
60
- }
61
- function detectHarness() {
62
- const env = process.env;
63
- const override = (env[ENV_KEYS.HARNESS_OVERRIDE] ?? "").toLowerCase().trim();
64
- if (override && KNOWN_HARNESS_NAMES.has(override)) {
65
- return override;
66
- }
67
- if (env["HERMES_SESSION_ID"] || env["HERMES_HOME"]) {
68
- return "hermes";
69
- }
70
- if (env["TERM_PROGRAM"] === "claude-code" || env["CLAUDE_CODE_VERSION"] !== void 0 || env["CLAUDE_CODE_SESSION_ID"] && env["CLAUDE_CODE_SESSION_ID"] !== relaySeededSessionIdValue) {
71
- return "claudecode";
72
- }
73
- if (env["CODEX_SESSION_ID"] !== void 0 || env["CODEX_SESSION"]) {
74
- return "codex";
75
- }
76
- if (env["OPENCODE_SESSION_ID"] !== void 0 || env["OPENCODE_SESSION"]) {
77
- return "opencode";
78
- }
79
- if (env["GROK_SESSION_ID"] !== void 0) {
80
- return "grok";
81
- }
82
- if (env["OPENCLAW_SESSION_ID"] !== void 0) {
83
- return "openclaw";
84
- }
85
- if (env["ANTHROPIC_API_KEY"]) {
86
- return "claudecode";
87
- }
88
- if (env["OPENAI_API_KEY"] && !env["ANTHROPIC_API_KEY"]) {
89
- return "codex";
90
- }
91
- if ((env["GEMINI_API_KEY"] || env["GOOGLE_API_KEY"]) && !env["ANTHROPIC_API_KEY"]) {
92
- return "gemini";
93
- }
94
- return "generic";
95
- }
96
- var _cached = null;
97
- function getHarnessName() {
98
- if (_cached === null) {
99
- _cached = detectHarness();
100
- }
101
- return _cached;
102
- }
103
- function resetHarnessCache() {
104
- _cached = null;
105
- }
106
- registerReset(resetHarnessCache, { perRequest: true });
107
-
108
- // src/fingerprint.ts
37
+ // src/config_project.ts
109
38
  init_define_import_meta_env();
110
- import { createHash } from "node:crypto";
111
39
  import * as fs from "node:fs";
112
- function fingerprintContent(content) {
113
- const hash = createHash("sha256");
114
- hash.update(typeof content === "string" ? Buffer.from(content, "utf-8") : content);
115
- return hash.digest("hex");
116
- }
117
- function shortFingerprint(content) {
118
- return fingerprintContent(content).slice(0, 16);
119
- }
120
- function fingerprintFile(filePath) {
121
- let data;
122
- try {
123
- data = fs.readFileSync(filePath);
124
- } catch {
125
- return null;
126
- }
127
- return fingerprintContent(data);
128
- }
129
- function fileIsAbsent(filePath) {
130
- try {
131
- return fs.statSync(filePath, { throwIfNoEntry: false }) === void 0;
132
- } catch {
133
- return false;
134
- }
135
- }
136
-
137
- // src/ocr_languages.ts
138
- init_define_import_meta_env();
139
- var DEFAULT_OCR_LANG = "eng";
140
- var SUPPORTED_OCR_LANG_CODES = [
141
- "eng",
142
- "fra",
143
- "spa",
144
- "deu",
145
- "ita",
146
- "por",
147
- "nld",
148
- "pol",
149
- "rus",
150
- "tur",
151
- "swe",
152
- "ara",
153
- "chi_sim",
154
- "chi_tra",
155
- "jpn",
156
- "kor"
157
- ];
158
- var SUPPORTED_SET = new Set(SUPPORTED_OCR_LANG_CODES);
159
- function isSupportedOcrLang(lang) {
160
- return SUPPORTED_SET.has(lang);
161
- }
162
- function resolveOcrLangs(input) {
163
- const result = [DEFAULT_OCR_LANG];
164
- if (!input) return result;
165
- const tokens = input.split(/[+,;\s]+/).map((s) => s.trim().toLowerCase());
166
- for (const token of tokens) {
167
- if (token && isSupportedOcrLang(token) && !result.includes(token)) {
168
- result.push(token);
169
- }
170
- }
171
- return result;
172
- }
173
-
174
- // src/project.ts
175
- init_define_import_meta_env();
176
- import * as fs2 from "node:fs";
177
- import * as os from "node:os";
178
40
  import * as path from "node:path";
179
- var PROJECT_MARKERS = [
180
- ".git",
181
- "package.json",
182
- "pyproject.toml",
183
- "Cargo.toml",
184
- "go.mod",
185
- "shopify.app.toml",
186
- "_config.yml",
187
- "deno.json",
188
- "deno.jsonc"
189
- ];
190
- var REPO_CONTAINER_THRESHOLD = 3;
191
- function projectHash(canonicalRoot) {
192
- return shortFingerprint(foldPath(canonicalRoot));
193
- }
194
- function makeProjectAt(root) {
195
- let canonical;
196
- try {
197
- canonical = canonicalize(root);
198
- } catch (exc) {
199
- throw new Error(
200
- `makeProjectAt: could not resolve path: ${extractErrorMessage(exc)}`,
201
- { cause: exc }
202
- );
203
- }
204
- try {
205
- const stat = fs2.statSync(canonical);
206
- if (!stat.isDirectory()) {
207
- throw new Error(`makeProjectAt: path is not a directory: ${canonical}`);
208
- }
209
- } catch (exc) {
210
- if (exc instanceof Error && exc.message.includes("ENOENT")) {
211
- throw new Error(`makeProjectAt: path does not exist: ${canonical}`, { cause: exc });
212
- }
213
- throw exc;
214
- }
215
- const hash = projectHash(canonical);
216
- return { root: canonical, hash, marker: "manual" };
217
- }
218
- function isRepoContainer(pathStr) {
219
- let nestedRepos = 0;
220
- try {
221
- const entries = fs2.readdirSync(pathStr, { withFileTypes: true });
222
- for (const entry of entries) {
223
- if (entry.isDirectory()) {
224
- const gitPath = path.join(pathStr, entry.name, ".git");
225
- if (fs2.existsSync(gitPath)) {
226
- let isGitDir = false;
227
- try {
228
- isGitDir = fs2.statSync(gitPath).isDirectory();
229
- } catch {
230
- }
231
- if (isGitDir) {
232
- nestedRepos++;
233
- if (nestedRepos >= REPO_CONTAINER_THRESHOLD) {
234
- return true;
235
- }
236
- }
237
- }
238
- }
239
- }
240
- } catch {
241
- return false;
242
- }
243
- return false;
244
- }
245
- function markerExists(current, marker) {
246
- const markerPath = path.join(current, marker);
247
- try {
248
- if (!fs2.existsSync(markerPath)) {
249
- return false;
250
- }
251
- const stat = fs2.lstatSync(markerPath);
252
- if (!stat.isSymbolicLink()) {
253
- return true;
254
- }
255
- const resolved = fs2.realpathSync(markerPath);
256
- const rel = path.relative(path.resolve(current), path.resolve(resolved));
257
- return !rel.startsWith("..") && !path.isAbsolute(rel);
258
- } catch {
259
- return false;
260
- }
261
- }
262
- function findProject(cwd) {
263
- let p;
264
- try {
265
- p = canonicalize(cwd);
266
- } catch {
267
- return null;
268
- }
269
- let sysTemp = null;
270
- try {
271
- sysTemp = canonicalize(os.tmpdir());
272
- } catch {
273
- }
274
- let current = p;
275
- while (true) {
276
- if (sysTemp && normalizeDarwinSystemAlias(foldPath(current)) === normalizeDarwinSystemAlias(foldPath(sysTemp))) {
277
- break;
278
- }
279
- for (const marker of PROJECT_MARKERS) {
280
- if (markerExists(current, marker)) {
281
- if (!isRepoContainer(current)) {
282
- return {
283
- root: current,
284
- hash: projectHash(current),
285
- marker
286
- };
287
- }
288
- break;
289
- }
290
- }
291
- const parent = path.dirname(current);
292
- if (parent === current) {
293
- break;
294
- }
295
- current = parent;
296
- }
297
- return null;
298
- }
299
- var _displayRootCache = null;
300
- function getDisplayRoot(explicitRoot) {
301
- if (explicitRoot !== void 0) return explicitRoot;
302
- const cwd = process.cwd();
303
- if (_displayRootCache !== null && _displayRootCache.cwd === cwd) return _displayRootCache.root;
304
- const project = findProject(cwd);
305
- const root = project !== null ? project.root : void 0;
306
- _displayRootCache = { cwd, root };
307
- return root;
308
- }
309
- registerReset(() => {
310
- _displayRootCache = null;
311
- }, { perRequest: true });
312
- function isUnderSystemTemp(filePath) {
313
- let sysTemp;
314
- try {
315
- sysTemp = canonicalize(os.tmpdir());
316
- } catch {
317
- return false;
318
- }
319
- let target;
320
- try {
321
- target = canonicalize(filePath);
322
- } catch {
323
- return false;
324
- }
325
- const foldedTemp = normalizeDarwinSystemAlias(foldPath(sysTemp));
326
- const foldedTarget = normalizeDarwinSystemAlias(foldPath(target));
327
- return foldedTarget === foldedTemp || foldedTarget.startsWith(`${foldedTemp}/`);
328
- }
329
- function resolveProjectRoot(opts) {
330
- const base = opts?.project !== void 0 ? path.resolve(opts.project) : process.cwd();
331
- const toplevel = runGit(["rev-parse", "--show-toplevel"], { cwd: base });
332
- if (toplevel.exitCode === 0) {
333
- const trimmed = toplevel.stdout.trim();
334
- if (trimmed.length > 0) return canonicalize(trimmed);
335
- }
336
- const project = findProject(base);
337
- if (project !== null) return project.root;
338
- return canonicalize(base);
339
- }
340
-
341
- // src/config_project.ts
342
- init_define_import_meta_env();
343
- import * as fs3 from "node:fs";
344
41
 
345
42
  // node_modules/smol-toml/dist/index.js
346
43
  init_define_import_meta_env();
@@ -354,107 +51,14 @@ init_define_import_meta_env();
354
51
  // node_modules/smol-toml/dist/primitive.js
355
52
  init_define_import_meta_env();
356
53
 
357
- // node_modules/smol-toml/dist/date.js
358
- init_define_import_meta_env();
359
- var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
360
- var TomlDate = class _TomlDate extends Date {
361
- #hasDate = false;
362
- #hasTime = false;
363
- #offset = null;
364
- constructor(date) {
365
- let hasDate = true;
366
- let hasTime = true;
367
- let offset = "Z";
368
- if (typeof date === "string") {
369
- let match = date.match(DATE_TIME_RE);
370
- if (match) {
371
- if (!match[1]) {
372
- hasDate = false;
373
- date = `0000-01-01T${date}`;
374
- }
375
- hasTime = !!match[2];
376
- hasTime && date[10] === " " && (date = date.replace(" ", "T"));
377
- if (match[2] && +match[2] > 23) {
378
- date = "";
379
- } else {
380
- offset = match[3] || null;
381
- date = date.toUpperCase();
382
- if (!offset && hasTime)
383
- date += "Z";
384
- }
385
- } else {
386
- date = "";
387
- }
388
- }
389
- super(date);
390
- if (!isNaN(this.getTime())) {
391
- this.#hasDate = hasDate;
392
- this.#hasTime = hasTime;
393
- this.#offset = offset;
394
- }
395
- }
396
- isDateTime() {
397
- return this.#hasDate && this.#hasTime;
398
- }
399
- isLocal() {
400
- return !this.#hasDate || !this.#hasTime || !this.#offset;
401
- }
402
- isDate() {
403
- return this.#hasDate && !this.#hasTime;
404
- }
405
- isTime() {
406
- return this.#hasTime && !this.#hasDate;
407
- }
408
- isValid() {
409
- return this.#hasDate || this.#hasTime;
410
- }
411
- toISOString() {
412
- let iso = super.toISOString();
413
- if (this.isDate())
414
- return iso.slice(0, 10);
415
- if (this.isTime())
416
- return iso.slice(11, 23);
417
- if (this.#offset === null)
418
- return iso.slice(0, -1);
419
- if (this.#offset === "Z")
420
- return iso;
421
- let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
422
- offset = this.#offset[0] === "-" ? offset : -offset;
423
- let offsetDate = new Date(this.getTime() - offset * 6e4);
424
- return offsetDate.toISOString().slice(0, -1) + this.#offset;
425
- }
426
- static wrapAsOffsetDateTime(jsDate, offset = "Z") {
427
- let date = new _TomlDate(jsDate);
428
- date.#offset = offset;
429
- return date;
430
- }
431
- static wrapAsLocalDateTime(jsDate) {
432
- let date = new _TomlDate(jsDate);
433
- date.#offset = null;
434
- return date;
435
- }
436
- static wrapAsLocalDate(jsDate) {
437
- let date = new _TomlDate(jsDate);
438
- date.#hasTime = false;
439
- date.#offset = null;
440
- return date;
441
- }
442
- static wrapAsLocalTime(jsDate) {
443
- let date = new _TomlDate(jsDate);
444
- date.#hasDate = false;
445
- date.#offset = null;
446
- return date;
447
- }
448
- };
449
-
450
54
  // node_modules/smol-toml/dist/error.js
451
55
  init_define_import_meta_env();
452
56
  function getLineColFromPtr(string, ptr) {
453
- let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g);
57
+ let lines = string.slice(0, ptr).split(/\r?\n/);
454
58
  return [lines.length, lines.pop().length + 1];
455
59
  }
456
60
  function makeCodeBlock(string, line, column) {
457
- let lines = string.split(/\r\n|\n|\r/g);
61
+ let lines = string.split(/\r?\n/);
458
62
  let codeblock = "";
459
63
  let numberLen = (Math.log10(line + 1) | 0) + 1;
460
64
  for (let i = line - 1; i <= line + 1; i++) {
@@ -472,7 +76,7 @@ function makeCodeBlock(string, line, column) {
472
76
  }
473
77
  return codeblock;
474
78
  }
475
- var TomlError = class extends Error {
79
+ var TomlError = class _TomlError extends Error {
476
80
  line;
477
81
  column;
478
82
  codeblock;
@@ -486,70 +90,15 @@ ${codeblock}`, options);
486
90
  this.column = column;
487
91
  this.codeblock = codeblock;
488
92
  }
489
- };
490
-
491
- // node_modules/smol-toml/dist/util.js
492
- init_define_import_meta_env();
493
- function indexOfNewline(str, start = 0) {
494
- let idx = str.indexOf("\n", start);
495
- if (str.charCodeAt(idx - 1) === 13)
496
- idx--;
497
- return idx;
498
- }
499
- function skipComment(ctx) {
500
- for (; ctx.p < ctx.s.length; ctx.p++) {
501
- let c = ctx.s.charCodeAt(ctx.p);
502
- if (c === 10)
503
- break;
504
- if (c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10) {
505
- ctx.p++;
506
- break;
507
- }
508
- if (c < 32 && c !== 9 || c === 127) {
509
- throw new TomlError("control characters are not allowed in comments", {
510
- toml: ctx.s,
511
- ptr: ctx.p
512
- });
513
- }
514
- }
515
- }
516
- function skipVoid(ctx, banNewLines, banComments) {
517
- let c;
518
- while (1) {
519
- while ((c = ctx.s.charCodeAt(ctx.p)) === 32 || c === 9 || !banNewLines && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10))
520
- ctx.p++;
521
- if (banComments || c !== 35)
522
- break;
523
- skipComment(ctx);
524
- }
525
- }
526
- function skipUntil(ctx, sep, end) {
527
- let ptr = ctx.p;
528
- if (!end) {
529
- ptr = indexOfNewline(ctx.s, ptr);
530
- ctx.p = ptr < 0 ? ctx.s.length : ptr;
531
- return;
93
+ /** @internal */
94
+ static x(message, ctx, ptr) {
95
+ throw new _TomlError(message, { toml: ctx.s, ptr: ptr ?? ctx.p });
532
96
  }
533
- for (; ctx.p < ctx.s.length; ctx.p++) {
534
- let c = ctx.s.charCodeAt(ctx.p);
535
- if (c === 35) {
536
- skipComment(ctx);
537
- } else if (c === end || c === sep) {
538
- return;
539
- }
540
- }
541
- throw new TomlError("cannot find end of structure", {
542
- toml: ctx.s,
543
- ptr
544
- });
545
- }
97
+ };
546
98
 
547
99
  // node_modules/smol-toml/dist/primitive.js
548
- var INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/;
549
- var FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/;
550
- var LEADING_ZERO = /^[+-]?0[0-9_]/;
551
100
  function parseString(ctx) {
552
- let start = ctx.p;
101
+ let startPtr = ctx.p;
553
102
  let c = ctx.s.charCodeAt(ctx.p++);
554
103
  let first = c;
555
104
  let isLiteral = c === 39;
@@ -568,10 +117,7 @@ function parseString(ctx) {
568
117
  if (isMultiline && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10)) {
569
118
  state = state && 3;
570
119
  } else if (c < 32 && c !== 9 || c === 127) {
571
- throw new TomlError("control characters are not allowed in strings", {
572
- toml: ctx.s,
573
- ptr: ctx.p
574
- });
120
+ TomlError.x("control characters are not allowed in strings", ctx);
575
121
  } else if ((!state || state === 3) && c === first && (!isMultiline || ctx.s.charCodeAt(ctx.p + 1) === first && ctx.s.charCodeAt(ctx.p + 2) === first)) {
576
122
  if (isMultiline) {
577
123
  if (ctx.s.charCodeAt(ctx.p + 3) === first)
@@ -579,8 +125,10 @@ function parseString(ctx) {
579
125
  if (ctx.s.charCodeAt(ctx.p + 3) === first)
580
126
  ctx.p++;
581
127
  }
582
- if (!state)
583
- parsed += ctx.s.slice(sliceStart, ctx.p);
128
+ if (!state) {
129
+ let s = ctx.s.slice(sliceStart, ctx.p);
130
+ parsed = parsed ? parsed + s : s;
131
+ }
584
132
  ctx.p += isMultiline ? 3 : 1;
585
133
  return parsed;
586
134
  } else if (!state) {
@@ -590,10 +138,11 @@ function parseString(ctx) {
590
138
  }
591
139
  } else if (state === 1) {
592
140
  if (c === 120 || c === 117 || c === 85) {
141
+ let errPtr = ctx.p++ - 1;
593
142
  let value = 0;
594
143
  let len = c === 120 ? 2 : c === 117 ? 4 : 8;
595
144
  for (let j = 0; j < len; j++, ctx.p++) {
596
- let hex = ctx.s.charCodeAt(ctx.p + 1);
145
+ let hex = ctx.s.charCodeAt(ctx.p);
597
146
  let digit = (
598
147
  /* 0-9 */
599
148
  hex >= 48 && hex <= 57 ? hex - 48 : (
@@ -605,16 +154,16 @@ function parseString(ctx) {
605
154
  )
606
155
  );
607
156
  if (digit < 0)
608
- throw new TomlError("invalid non-hex character in unicode escape", { toml: ctx.s, ptr: ctx.p + 1 });
157
+ TomlError.x("invalid non-hex character in unicode escape", ctx);
609
158
  value = value << 4 | digit;
610
159
  }
611
160
  if (value < 0 || value > 1114111 || value >= 55296 && value <= 57343) {
612
- throw new TomlError("invalid unicode escape", { toml: ctx.s, ptr: ctx.p });
161
+ TomlError.x("invalid unicode escape", ctx, errPtr);
613
162
  }
614
163
  parsed += String.fromCodePoint(value);
615
- sliceStart = ctx.p + 1;
164
+ sliceStart = ctx.p--;
616
165
  state = 0;
617
- } else if (c === 32 || c === 9) {
166
+ } else if (isMultiline && (c === 32 || c === 9)) {
618
167
  state = 2;
619
168
  } else {
620
169
  if (c === 98)
@@ -634,85 +183,154 @@ function parseString(ctx) {
634
183
  else if (c === 92)
635
184
  parsed += "\\";
636
185
  else
637
- throw new TomlError("unrecognized escape sequence", { toml: ctx.s, ptr: ctx.p });
186
+ TomlError.x("unrecognised escape sequence", ctx);
638
187
  sliceStart = ctx.p + 1;
639
188
  state = 0;
640
189
  }
641
190
  } else if (c !== 32 && c !== 9) {
642
- if (state === 2) {
643
- throw new TomlError("invalid escape: only line-ending whitespace may be escaped", {
644
- toml: ctx.s,
645
- ptr: sliceStart
646
- });
647
- }
191
+ if (state === 2)
192
+ TomlError.x("invalid escape: only line-ending whitespace may be escaped", ctx, sliceStart);
648
193
  state = !isLiteral && c === 92 ? 1 : 0;
649
194
  sliceStart = ctx.p;
650
195
  }
651
196
  }
652
- throw new TomlError("unfinished string", { toml: ctx.s, ptr: start });
653
- }
654
- function sliceAndTrimEndOf(ctx, start, end) {
655
- let value = ctx.s.slice(start, end);
656
- let commentIdx = value.indexOf("#");
657
- if (commentIdx > 0) {
658
- skipComment({ s: value, p: commentIdx, d: 0 });
659
- value = value.slice(0, commentIdx);
660
- }
661
- return value.trimEnd();
662
- }
663
- function parseValue(ctx, integersAsBigInt, end) {
664
- let ptr = ctx.p;
665
- let err = { toml: ctx.s, ptr };
666
- skipUntil(ctx, 44, end);
667
- let value = sliceAndTrimEndOf(ctx, ptr, ctx.p);
668
- if (!value)
669
- throw new TomlError("incomplete declaration: value expected", err);
670
- if (value === "-inf")
671
- return -Infinity;
672
- if (value === "inf" || value === "+inf")
673
- return Infinity;
674
- if (value === "nan" || value === "+nan" || value === "-nan")
675
- return NaN;
676
- if (value === "-0")
677
- return integersAsBigInt ? 0n : 0;
678
- let isInt = INT_REGEX.test(value);
679
- if (isInt || FLOAT_REGEX.test(value)) {
680
- if (LEADING_ZERO.test(value)) {
681
- throw new TomlError("leading zeroes are not allowed", err);
682
- }
683
- value = value.replace(/_/g, "");
684
- let numeric = +value;
685
- if (isNaN(numeric)) {
686
- throw new TomlError("invalid number", err);
687
- }
688
- if (isInt) {
689
- if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) {
690
- throw new TomlError("integer value cannot be represented losslessly", err);
197
+ TomlError.x("unfinished string", ctx, startPtr);
198
+ }
199
+
200
+ // node_modules/smol-toml/dist/extract.js
201
+ init_define_import_meta_env();
202
+
203
+ // node_modules/smol-toml/dist/date.js
204
+ init_define_import_meta_env();
205
+ var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[Tt ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|z|[-+]\d{2}:\d{2})?$/i;
206
+ var TomlDate = class _TomlDate extends Date {
207
+ #hasDate = false;
208
+ #hasTime = false;
209
+ #offset = null;
210
+ constructor(date, fasttype, unsafeDelim) {
211
+ let hasDate = true;
212
+ let hasTime = true;
213
+ let offset = "Z";
214
+ let c;
215
+ if (typeof date === "string") {
216
+ if (fasttype)
217
+ prep: {
218
+ if (fasttype < 3) {
219
+ if (+date.slice(11, 13) > 23) {
220
+ date = "";
221
+ break prep;
222
+ }
223
+ if (fasttype === 2) {
224
+ offset = null;
225
+ date += "Z";
226
+ } else if ((c = date.charCodeAt(date.length - 1)) !== 90 && c !== 122) {
227
+ offset = date.slice(date.length - 6);
228
+ }
229
+ if (unsafeDelim)
230
+ date = date.slice(0, 10) + "T" + date.slice(11);
231
+ } else if (fasttype === 4) {
232
+ date = +date.slice(0, 2) > 23 ? "" : `0000-01-01T${date}Z`;
233
+ }
234
+ hasDate = fasttype !== 4;
235
+ hasTime = fasttype !== 3;
236
+ }
237
+ else {
238
+ let match = date.match(DATE_TIME_RE);
239
+ if (match) {
240
+ if (!match[1]) {
241
+ hasDate = false;
242
+ date = `0000-01-01T${date}`;
243
+ }
244
+ hasTime = !!match[2];
245
+ hasTime && date[10] === " " && (date = date.replace(" ", "T"));
246
+ if (match[2] && +match[2] > 23) {
247
+ date = "";
248
+ } else {
249
+ offset = match[3] || null;
250
+ if (!offset && hasTime)
251
+ date += "Z";
252
+ }
253
+ } else {
254
+ date = "";
255
+ }
691
256
  }
692
- if (isInt || integersAsBigInt === true)
693
- numeric = BigInt(value);
694
257
  }
695
- return numeric;
258
+ super(date);
259
+ if (!isNaN(this.getTime())) {
260
+ this.#hasDate = hasDate;
261
+ this.#hasTime = hasTime;
262
+ this.#offset = offset;
263
+ }
696
264
  }
697
- const date = new TomlDate(value);
698
- if (!date.isValid())
699
- throw new TomlError("invalid value", err);
700
- return date;
701
- }
265
+ isDateTime() {
266
+ return this.#hasDate && this.#hasTime;
267
+ }
268
+ isLocal() {
269
+ return !this.#hasDate || !this.#hasTime || !this.#offset;
270
+ }
271
+ isDate() {
272
+ return this.#hasDate && !this.#hasTime;
273
+ }
274
+ isTime() {
275
+ return this.#hasTime && !this.#hasDate;
276
+ }
277
+ isValid() {
278
+ return this.#hasDate || this.#hasTime;
279
+ }
280
+ toISOString() {
281
+ let iso = super.toISOString();
282
+ if (this.isDate())
283
+ return iso.slice(0, 10);
284
+ if (this.isTime())
285
+ return iso.slice(11, 23);
286
+ if (this.#offset === null)
287
+ return iso.slice(0, -1);
288
+ if (this.#offset === "Z" || this.#offset === "z")
289
+ return iso;
290
+ let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
291
+ offset = this.#offset[0] === "-" ? offset : -offset;
292
+ let offsetDate = new Date(this.getTime() - offset * 6e4);
293
+ return offsetDate.toISOString().slice(0, -1) + this.#offset;
294
+ }
295
+ static wrapAsOffsetDateTime(jsDate, offset = "Z") {
296
+ let date = new _TomlDate(jsDate);
297
+ date.#offset = offset;
298
+ return date;
299
+ }
300
+ static wrapAsLocalDateTime(jsDate) {
301
+ let date = new _TomlDate(jsDate);
302
+ date.#offset = null;
303
+ return date;
304
+ }
305
+ static wrapAsLocalDate(jsDate) {
306
+ let date = new _TomlDate(jsDate);
307
+ date.#hasTime = false;
308
+ date.#offset = null;
309
+ return date;
310
+ }
311
+ static wrapAsLocalTime(jsDate) {
312
+ let date = new _TomlDate(jsDate);
313
+ date.#hasDate = false;
314
+ date.#offset = null;
315
+ return date;
316
+ }
317
+ };
702
318
 
703
319
  // node_modules/smol-toml/dist/extract.js
704
- init_define_import_meta_env();
705
- function extractValue(ctx, end, integersAsBigInt) {
706
- let ptr = ctx.p;
707
- let c = ctx.s.charCodeAt(ptr);
320
+ function isDigit(char, base = 10) {
321
+ return base === 16 ? char > 47 && char < 58 || char > 64 && char < 71 || char > 96 && char < 103 : char > 47 && char < 48 + base;
322
+ }
323
+ function isEndOfValue(char, delim) {
324
+ return char === 32 || char === 9 || char === 10 || char === 13 || // Structure end or next value delimiter
325
+ delim && (char === delim || char === 44) || // Comment
326
+ char === 35;
327
+ }
328
+ function extractValue(ctx, end) {
329
+ let errPtr = ctx.p;
330
+ let c = ctx.s.charCodeAt(ctx.p);
708
331
  if (c === 91 || c === 123) {
709
- if (!ctx.d--) {
710
- throw new TomlError("document contains excessively nested structures. aborting.", {
711
- toml: ctx.s,
712
- ptr
713
- });
714
- }
715
- let value = c === 91 ? parseArray(ctx, integersAsBigInt) : parseInlineTable(ctx, integersAsBigInt);
332
+ ctx.d-- || TomlError.x("document contains excessively nested structures. aborting.", ctx);
333
+ let value = c === 91 ? parseArray(ctx) : parseInlineTable(ctx);
716
334
  ctx.d++;
717
335
  return value;
718
336
  }
@@ -721,90 +339,263 @@ function extractValue(ctx, end, integersAsBigInt) {
721
339
  }
722
340
  if (c === 116) {
723
341
  if (ctx.s.charCodeAt(++ctx.p) !== 114 || ctx.s.charCodeAt(++ctx.p) !== 117 || ctx.s.charCodeAt(++ctx.p) !== 101)
724
- throw new TomlError("invalid value", { toml: ctx.s, ptr });
725
- ctx.p++;
726
- return true;
342
+ TomlError.x("invalid value", ctx, errPtr);
343
+ return ctx.p++, true;
727
344
  }
728
345
  if (c === 102) {
729
346
  if (ctx.s.charCodeAt(++ctx.p) !== 97 || ctx.s.charCodeAt(++ctx.p) !== 108 || ctx.s.charCodeAt(++ctx.p) !== 115 || ctx.s.charCodeAt(++ctx.p) !== 101)
730
- throw new TomlError("invalid value", { toml: ctx.s, ptr });
731
- ctx.p++;
732
- return false;
347
+ TomlError.x("invalid value", ctx, errPtr);
348
+ return ctx.p++, false;
349
+ }
350
+ if (c === 43 || c === 45) {
351
+ return parseNumber(ctx, ctx.p, ctx.s.charCodeAt(++ctx.p), 44 - c, end);
352
+ }
353
+ if (ctx.s.charCodeAt(ctx.p + 4) === 45 && ctx.s.charCodeAt(ctx.p + 7) === 45) {
354
+ return parseDate(ctx, c, end);
355
+ }
356
+ if (ctx.s.charCodeAt(ctx.p + 2) === 58) {
357
+ return parseTime(ctx, c, end);
358
+ }
359
+ return parseNumber(ctx, ctx.p, c, 0, end);
360
+ }
361
+ function parseNumber(ctx, startPtr, startChr, sign, endChr) {
362
+ let c = startChr;
363
+ let state = 0;
364
+ let hasUnderscores = false;
365
+ if (c === 105) {
366
+ if (ctx.s.charCodeAt(++ctx.p) !== 110 || ctx.s.charCodeAt(++ctx.p) !== 102)
367
+ TomlError.x("invalid value", ctx, startPtr);
368
+ return ctx.p++, (sign || 1) / 0;
369
+ }
370
+ if (c === 110) {
371
+ if (ctx.s.charCodeAt(++ctx.p) !== 97 || ctx.s.charCodeAt(++ctx.p) !== 110)
372
+ TomlError.x("invalid value", ctx, startPtr);
373
+ return ctx.p++, NaN;
374
+ }
375
+ if (c === 48) {
376
+ if (++ctx.p >= ctx.s.length || isEndOfValue(c = ctx.s.charCodeAt(ctx.p), endChr))
377
+ return ctx.bi === true ? 0n : 0;
378
+ if (!sign) {
379
+ if (c === 120)
380
+ return parseIntegerBaseN(ctx, startPtr, 16, endChr);
381
+ else if (c === 98)
382
+ return parseIntegerBaseN(ctx, startPtr, 2, endChr);
383
+ else if (c === 111)
384
+ return parseIntegerBaseN(ctx, startPtr, 8, endChr);
385
+ }
386
+ if (c === 46)
387
+ state = 2;
388
+ else if (c === 101 || c === 69)
389
+ state = 4;
390
+ else
391
+ TomlError.x("illegal leading zero", ctx, startPtr);
392
+ } else if (!isDigit(c))
393
+ TomlError.x("invalid value", ctx, startPtr);
394
+ while (++ctx.p < ctx.s.length && (c = ctx.s.charCodeAt(ctx.p), !isEndOfValue(c, endChr))) {
395
+ if (!state)
396
+ state = 1;
397
+ if (c === 95) {
398
+ if (!(state & 1))
399
+ TomlError.x("illegal underscore", ctx);
400
+ state += 11;
401
+ hasUnderscores = true;
402
+ } else if (state === 1 && c === 46)
403
+ state = 2;
404
+ else if ((state === 1 || state === 3) && (c === 101 || c === 69))
405
+ state = 4;
406
+ else if (state === 4 && (c === 43 || c === 45)) {
407
+ } else if (!isDigit(c))
408
+ TomlError.x(`illegal character in numeric literal`, ctx);
409
+ else if (state > 9)
410
+ state -= 11;
411
+ else if (!(state & 1))
412
+ state++;
413
+ }
414
+ if (!state) {
415
+ let val = (startChr - 48) * (sign || 1);
416
+ return ctx.bi === true ? BigInt(val) : val;
417
+ }
418
+ if (!(state & 1))
419
+ TomlError.x("unfinished numeric value", ctx, startPtr);
420
+ let str = ctx.s.slice(startPtr, ctx.p);
421
+ if (hasUnderscores)
422
+ str = str.replaceAll("_", "");
423
+ return state > 1 ? parseFloat(str) : parseInteger(ctx, str, 10, startPtr);
424
+ }
425
+ function parseIntegerBaseN(ctx, startPtr, base, endChr) {
426
+ let c, underscore = 1;
427
+ while (++ctx.p < ctx.s.length && (c = ctx.s.charCodeAt(ctx.p), !isEndOfValue(c, endChr))) {
428
+ if (c === 95) {
429
+ if (underscore & 1)
430
+ TomlError.x("illegal underscore", ctx);
431
+ underscore = 3;
432
+ } else if (!isDigit(c, base))
433
+ TomlError.x(`illegal character in numeric literal`, ctx);
434
+ else if (underscore & 1)
435
+ underscore--;
436
+ }
437
+ if (underscore & 1)
438
+ TomlError.x("unfinished numeric value", ctx);
439
+ let str = ctx.s.slice(startPtr + 2, ctx.p);
440
+ if (underscore)
441
+ str = str.replaceAll("_", "");
442
+ return parseInteger(ctx, str, base, startPtr);
443
+ }
444
+ function parseInteger(ctx, str, base, startPtr) {
445
+ if (ctx.bi !== true)
446
+ int: {
447
+ let val = parseInt(str, base);
448
+ if (!Number.isSafeInteger(val)) {
449
+ if (ctx.bi)
450
+ break int;
451
+ TomlError.x("integer value cannot be represented losslessly", ctx, startPtr);
452
+ }
453
+ return val;
454
+ }
455
+ return base === 10 ? BigInt(str) : BigInt((base === 2 ? "0b" : base === 8 ? "0o" : "0x") + str);
456
+ }
457
+ function parseDate(ctx, c, endChr) {
458
+ let startPtr = ctx.p++, unsafeSeparator;
459
+ if (!isDigit(c) || !isDigit(ctx.s.charCodeAt(ctx.p++)) || !isDigit(ctx.s.charCodeAt(ctx.p++)) || !isDigit(ctx.s.charCodeAt(ctx.p++))) {
460
+ return parseNumber(ctx, ctx.p = startPtr, c, 0, endChr);
461
+ }
462
+ ctx.p += 5;
463
+ if (!isDigit(ctx.s.charCodeAt(ctx.p++)))
464
+ TomlError.x("invalid date-time: date part is malformed", ctx, startPtr);
465
+ if (ctx.p >= ctx.s.length || ((c = ctx.s.charCodeAt(ctx.p)) !== 32 || (unsafeSeparator = true, !isDigit(ctx.s.charCodeAt(ctx.p + 1)))) && c !== 84 && c !== 116) {
466
+ let t2 = ctx.s.slice(startPtr, ctx.p);
467
+ return readDate(ctx, t2, 3, false, startPtr);
468
+ }
469
+ if (ctx.s.charCodeAt(ctx.p += 3) !== 58)
470
+ TomlError.x("invalid date-time: time part is malformed", ctx, startPtr);
471
+ if (ctx.s.charCodeAt(ctx.p += 3) === 58)
472
+ ctx.p += 3;
473
+ if (ctx.s.charCodeAt(ctx.p) === 46)
474
+ while (isDigit(ctx.s.charCodeAt(++ctx.p)))
475
+ ;
476
+ if (c = ctx.s.charCodeAt(ctx.p)) {
477
+ if (c === 90 || c === 122) {
478
+ let t2 = ctx.s.slice(startPtr, ++ctx.p);
479
+ return readDate(ctx, t2, 1, unsafeSeparator, startPtr, "[+00:00]");
480
+ }
481
+ if (c === 43 || c === 45) {
482
+ let t2 = ctx.s.slice(startPtr, ctx.p += 6);
483
+ return readDate(ctx, t2, 1, unsafeSeparator, startPtr, !ctx.ld && "[" + ctx.s.slice(ctx.p - 6, ctx.p) + "]");
484
+ }
485
+ }
486
+ let t = ctx.s.slice(startPtr, ctx.p);
487
+ return readDate(ctx, t, 2, unsafeSeparator, startPtr);
488
+ }
489
+ function parseTime(ctx, c, endChr) {
490
+ let start = ctx.p;
491
+ if (!isDigit(c) || !isDigit(ctx.s.charCodeAt(++ctx.p))) {
492
+ return parseNumber(ctx, --ctx.p, c, 0, endChr);
493
+ }
494
+ if (ctx.s.charCodeAt(ctx.p += 4) === 58)
495
+ ctx.p += 3;
496
+ if (ctx.s.charCodeAt(ctx.p) === 46)
497
+ while (isDigit(ctx.s.charCodeAt(++ctx.p)))
498
+ ;
499
+ let t = ctx.s.slice(start, ctx.p);
500
+ return readDate(ctx, t, 4, false, start);
501
+ }
502
+ function readDate(ctx, str, type, unsafeDelim, errPtr, temporalSuffix) {
503
+ if (ctx.ld) {
504
+ let date = new TomlDate(str, type, unsafeDelim);
505
+ if (!date.isValid())
506
+ TomlError.x("invalid date", ctx, errPtr);
507
+ return date;
508
+ }
509
+ try {
510
+ if (temporalSuffix)
511
+ str += temporalSuffix;
512
+ switch (type) {
513
+ case 1:
514
+ return Temporal.ZonedDateTime.from(str);
515
+ case 2:
516
+ return Temporal.PlainDateTime.from(str);
517
+ case 3:
518
+ return Temporal.PlainDate.from(str);
519
+ case 4:
520
+ return Temporal.PlainTime.from(str);
521
+ }
522
+ } catch (e) {
523
+ TomlError.x(e instanceof Error ? e.message : "" + e, ctx, errPtr);
524
+ }
525
+ }
526
+
527
+ // node_modules/smol-toml/dist/util.js
528
+ init_define_import_meta_env();
529
+ function skipComment(ctx) {
530
+ for (; ctx.p < ctx.s.length; ctx.p++) {
531
+ let c = ctx.s.charCodeAt(ctx.p);
532
+ if (c === 10)
533
+ break;
534
+ if (c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10) {
535
+ ctx.p++;
536
+ break;
537
+ }
538
+ if (c < 32 && c !== 9 || c === 127) {
539
+ TomlError.x("control characters are not allowed in comments", ctx);
540
+ }
541
+ }
542
+ }
543
+ function skipVoid(ctx, banNewLines, banComments) {
544
+ let c;
545
+ while (ctx.p < ctx.s.length) {
546
+ while (ctx.p < ctx.s.length && ((c = ctx.s.charCodeAt(ctx.p)) === 32 || c === 9 || !banNewLines && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10)))
547
+ ctx.p++;
548
+ if (banComments || c !== 35)
549
+ break;
550
+ skipComment(ctx);
733
551
  }
734
- return parseValue(ctx, integersAsBigInt, end);
735
552
  }
736
553
 
737
554
  // node_modules/smol-toml/dist/struct.js
738
- var KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
739
- function parseKey(ctx, end = "=") {
740
- let start = ctx.p;
741
- let dot = start - 1;
555
+ function parseKey(ctx, end = 61) {
556
+ let startPtr;
557
+ let state = 0;
742
558
  let parsed = [];
743
- let endPtr = ctx.s.indexOf(end, start);
744
- if (endPtr < 0) {
745
- throw new TomlError("incomplete key-value: cannot find end of key", {
746
- toml: ctx.s,
747
- ptr: start
748
- });
749
- }
559
+ let sliceStart;
560
+ let c = ctx.s.charCodeAt(startPtr = ctx.p);
750
561
  do {
751
- let c = ctx.s.charCodeAt(ctx.p = ++dot);
752
- if (c !== 32 && c !== 9) {
753
- if (c === 34 || c === 39) {
754
- if (c === ctx.s.charCodeAt(ctx.p + 1) && c === ctx.s.charCodeAt(ctx.p + 2)) {
755
- throw new TomlError("multiline strings are not allowed in keys", {
756
- toml: ctx.s,
757
- ptr: ctx.p
758
- });
759
- }
760
- let part = parseString(ctx);
761
- dot = ctx.s.indexOf(".", ctx.p);
762
- let strEnd = ctx.s.slice(ctx.p, dot < 0 || dot > endPtr ? endPtr : dot);
763
- let newLine = indexOfNewline(strEnd);
764
- if (newLine > -1) {
765
- throw new TomlError("newlines are not allowed in keys", {
766
- toml: ctx.s,
767
- ptr: newLine
768
- });
769
- }
770
- if (strEnd.trimStart()) {
771
- throw new TomlError("found extra tokens after the string part", {
772
- toml: ctx.s,
773
- ptr: ctx.p
774
- });
775
- }
776
- if (endPtr < ctx.p) {
777
- endPtr = ctx.s.indexOf(end, ctx.p);
778
- if (endPtr < 0) {
779
- throw new TomlError("incomplete key-value: cannot find end of key", {
780
- toml: ctx.s,
781
- ptr: start
782
- });
783
- }
784
- }
785
- parsed.push(part);
786
- } else {
787
- dot = ctx.s.indexOf(".", ctx.p);
788
- let part = ctx.s.slice(ctx.p, dot < 0 || dot > endPtr ? endPtr : dot);
789
- if (!KEY_PART_RE.test(part)) {
790
- throw new TomlError("only letter, numbers, dashes and underscores are allowed in keys", {
791
- toml: ctx.s,
792
- ptr: ctx.p
793
- });
794
- }
795
- parsed.push(part.trimEnd());
562
+ if (c === end) {
563
+ if (!state)
564
+ TomlError.x("unexpected end of key", ctx);
565
+ if (state === 1)
566
+ parsed.push(ctx.s.slice(sliceStart, ctx.p));
567
+ return ctx.p++, parsed;
568
+ } else if (c === 46) {
569
+ if (!state)
570
+ TomlError.x("illegal empty bare key", ctx);
571
+ if (state === 1)
572
+ parsed.push(ctx.s.slice(sliceStart, ctx.p));
573
+ state = 0;
574
+ } else if (!state && (c === 34 || c === 39)) {
575
+ if (c === ctx.s.charCodeAt(ctx.p + 1) && c === ctx.s.charCodeAt(ctx.p + 2))
576
+ TomlError.x("illegal quoted key: multiline strings are not allowed", ctx);
577
+ parsed.push(parseString(ctx));
578
+ state = 2;
579
+ ctx.p--;
580
+ } else if (c === 32 || c === 9) {
581
+ if (state === 1) {
582
+ parsed.push(ctx.s.slice(sliceStart, ctx.p));
583
+ state = 2;
796
584
  }
585
+ } else if (state === 2 || c < 48 && c !== 45 || c > 57 && c < 65 || c > 90 && c < 97 && c !== 95 || c > 122) {
586
+ TomlError.x("illegal character in key", ctx);
587
+ } else if (!state) {
588
+ state = 1;
589
+ sliceStart = ctx.p;
797
590
  }
798
- } while (dot + 1 && dot < endPtr);
799
- ctx.p = endPtr + 1;
800
- skipVoid(ctx, true, true);
801
- return parsed;
591
+ } while (c = ctx.s.charCodeAt(++ctx.p));
592
+ TomlError.x("incomplete key-value: cannot find end of key", ctx, startPtr);
802
593
  }
803
- function parseInlineTable(ctx, integersAsBigInt) {
804
- let res = {};
594
+ function parseInlineTable(ctx) {
595
+ let startPtr = ctx.p++;
596
+ let res = /* @__PURE__ */ Object.create(null);
805
597
  let seen = /* @__PURE__ */ new Set();
806
598
  let c;
807
- ctx.p++;
808
599
  while (ctx.p < ctx.s.length) {
809
600
  skipVoid(ctx);
810
601
  if ((c = ctx.s.charCodeAt(ctx.p)) === 125) {
@@ -814,70 +605,71 @@ function parseInlineTable(ctx, integersAsBigInt) {
814
605
  let k;
815
606
  let t = res;
816
607
  let hasOwn = false;
817
- let p = ctx.p;
608
+ let errPtr = ctx.p;
818
609
  let key = parseKey(ctx);
819
610
  for (let i = 0; i < key.length; i++) {
820
611
  if (i)
821
- t = hasOwn ? t[k] : t[k] = {};
612
+ t = hasOwn ? t[k] : t[k] = /* @__PURE__ */ Object.create(null);
822
613
  k = key[i];
823
614
  if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) {
824
- throw new TomlError("trying to redefine an already defined value", {
825
- toml: ctx.s,
826
- ptr: p
827
- });
615
+ TomlError.x("trying to redefine an already defined value", ctx, errPtr);
828
616
  }
829
- if (!hasOwn && k === "__proto__") {
617
+ let unsafe = k === "__proto__";
618
+ if (ctx.uk && (unsafe || k === "constructor")) {
619
+ t = ctx.uk !== 1 && TomlError.x("document contains an unsafe property", ctx, errPtr);
620
+ break;
621
+ }
622
+ if (!hasOwn && unsafe) {
830
623
  Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
831
624
  }
832
625
  }
833
626
  if (hasOwn) {
834
- throw new TomlError("trying to redefine an already defined value", {
835
- toml: ctx.s,
836
- ptr: ctx.p
837
- });
627
+ TomlError.x("trying to redefine an already defined value", ctx, errPtr);
838
628
  }
839
- let value = extractValue(ctx, 125, integersAsBigInt);
840
- seen.add(t[k] = value);
629
+ skipVoid(ctx, true, true);
630
+ let value = extractValue(
631
+ ctx,
632
+ 125
633
+ /* } */
634
+ );
635
+ if (t && typeof (t[k] = value) === "object")
636
+ seen.add(value);
841
637
  skipVoid(ctx);
842
638
  if ((c = ctx.s.charCodeAt(ctx.p++)) === 125) {
843
639
  return res;
844
640
  }
845
- if (c !== 44) {
846
- throw new TomlError("expected comma or end of structure", { toml: ctx.s, ptr: ctx.p - 1 });
847
- }
641
+ if (c !== 44)
642
+ TomlError.x("expected comma or end of structure", ctx, ctx.p - 1);
848
643
  }
849
- throw new TomlError("unfinished table encountered", {
850
- toml: ctx.s,
851
- ptr: ctx.p
852
- });
644
+ TomlError.x("unfinished table", ctx, startPtr);
853
645
  }
854
- function parseArray(ctx, integersAsBigInt) {
646
+ function parseArray(ctx) {
647
+ let startPtr = ctx.p++;
855
648
  let res = [];
856
649
  let c;
857
- ctx.p++;
858
650
  while (ctx.p < ctx.s.length) {
859
651
  skipVoid(ctx);
860
652
  if ((c = ctx.s.charCodeAt(ctx.p)) === 93) {
861
653
  ctx.p++;
862
654
  return res;
863
655
  }
864
- res.push(extractValue(ctx, 93, integersAsBigInt));
656
+ res.push(extractValue(
657
+ ctx,
658
+ 93
659
+ /* ] */
660
+ ));
865
661
  skipVoid(ctx);
866
662
  if ((c = ctx.s.charCodeAt(ctx.p++)) === 93) {
867
663
  return res;
868
664
  }
869
- if (c !== 44) {
870
- throw new TomlError("expected comma or end of structure", { toml: ctx.s, ptr: ctx.p - 1 });
871
- }
665
+ if (c !== 44)
666
+ TomlError.x("expected comma or end of structure", ctx, ctx.p - 1);
872
667
  }
873
- throw new TomlError("unfinished array encountered", {
874
- toml: ctx.s,
875
- ptr: ctx.p
876
- });
668
+ TomlError.x("unfinished array", ctx, startPtr);
877
669
  }
878
670
 
879
671
  // node_modules/smol-toml/dist/parse.js
880
- function peekTable(key, table, meta, type) {
672
+ function peekTable(ctx, key, table, meta, type) {
881
673
  let t = table;
882
674
  let m = meta;
883
675
  let k;
@@ -885,7 +677,7 @@ function peekTable(key, table, meta, type) {
885
677
  let state;
886
678
  for (let i = 0; i < key.length; i++) {
887
679
  if (i) {
888
- t = hasOwn ? t[k] : t[k] = {};
680
+ t = hasOwn ? t[k] : t[k] = /* @__PURE__ */ Object.create(null);
889
681
  m = (state = m[k]).c;
890
682
  if (type === 0 && (state.t === 1 || state.t === 2)) {
891
683
  return null;
@@ -901,7 +693,10 @@ function peekTable(key, table, meta, type) {
901
693
  return null;
902
694
  }
903
695
  if (!hasOwn) {
904
- if (k === "__proto__") {
696
+ let unsafe = k === "__proto__";
697
+ if (ctx.uk && (unsafe || k === "constructor"))
698
+ return false;
699
+ if (unsafe) {
905
700
  Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
906
701
  Object.defineProperty(m, k, { enumerable: true, configurable: true, writable: true });
907
702
  }
@@ -909,7 +704,7 @@ function peekTable(key, table, meta, type) {
909
704
  t: i < key.length - 1 && type === 2 ? 3 : type,
910
705
  d: false,
911
706
  i: 0,
912
- c: {}
707
+ c: /* @__PURE__ */ Object.create(null)
913
708
  };
914
709
  }
915
710
  }
@@ -922,43 +717,60 @@ function peekTable(key, table, meta, type) {
922
717
  state.d = true;
923
718
  t[k] = [];
924
719
  }
925
- t[k].push(t = {});
926
- state.c[state.i++] = state = { t: 1, d: false, i: 0, c: {} };
720
+ t[k].push(t = /* @__PURE__ */ Object.create(null));
721
+ state.c[state.i++] = state = { t: 1, d: false, i: 0, c: /* @__PURE__ */ Object.create(null) };
927
722
  }
928
723
  if (state.d) {
929
724
  return null;
930
725
  }
931
726
  state.d = true;
932
727
  if (type === 1) {
933
- t = hasOwn ? t[k] : t[k] = {};
728
+ t = hasOwn ? t[k] : t[k] = /* @__PURE__ */ Object.create(null);
934
729
  } else if (type === 0 && hasOwn) {
935
730
  return null;
936
731
  }
937
732
  return [k, t, state.c];
938
733
  }
939
- function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
940
- let ctx = { s: toml, p: 0, d: maxDepth };
941
- let res = {};
942
- let meta = {};
734
+ function validateTablePeek(ctx, peek, ptr) {
735
+ if (peek === null || ctx.uk === 2)
736
+ TomlError.x(peek === null ? "trying to redefine an already defined table or value" : "document contains an unsafe property", ctx, ptr);
737
+ }
738
+ function parse(toml, options = {}) {
739
+ let ctx = {
740
+ s: toml,
741
+ p: 0,
742
+ d: options.maxDepth ?? 1e3,
743
+ bi: options.integersAsBigInt ?? false,
744
+ ld: options.useLegacyDate ?? true,
745
+ uk: options.unsafeKeyBehaviour === "throw" ? 2 : options.unsafeKeyBehaviour === "drop" ? 1 : 0
746
+ };
747
+ let res = /* @__PURE__ */ Object.create(null);
748
+ let meta = /* @__PURE__ */ Object.create(null);
943
749
  let tmp;
750
+ let skipping = false;
944
751
  let tbl = res;
945
752
  let m = meta;
753
+ if (toml.charCodeAt(0) === 65279)
754
+ ctx.p++;
946
755
  skipVoid(ctx);
947
756
  while (ctx.p < toml.length) {
948
757
  if (toml.charCodeAt(ctx.p) === 91) {
949
758
  let isTableArray = toml.charCodeAt(++ctx.p) === 91;
950
759
  tmp = ctx.p += +isTableArray;
951
- let k = parseKey(ctx, "]");
760
+ skipping = false;
761
+ let k = parseKey(
762
+ ctx,
763
+ 93
764
+ /* ] */
765
+ );
952
766
  if (isTableArray) {
953
- if (toml.charCodeAt(ctx.p - 1) !== 93) {
954
- throw new TomlError("expected end of table declaration", {
955
- toml,
956
- ptr: ctx.p - 1
957
- });
767
+ if (toml.charCodeAt(ctx.p) !== 93) {
768
+ TomlError.x("expected end of table array declaration", ctx);
958
769
  }
959
770
  ctx.p++;
960
771
  }
961
772
  let p = peekTable(
773
+ ctx,
962
774
  k,
963
775
  res,
964
776
  meta,
@@ -966,37 +778,33 @@ function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
966
778
  /* Type.EXPLICIT */
967
779
  );
968
780
  if (!p) {
969
- throw new TomlError("trying to redefine an already defined table or value", {
970
- toml,
971
- ptr: tmp
972
- });
781
+ validateTablePeek(ctx, p, tmp);
782
+ skipping = true;
783
+ } else {
784
+ m = p[2];
785
+ tbl = p[1];
973
786
  }
974
- m = p[2];
975
- tbl = p[1];
976
787
  } else {
977
788
  tmp = ctx.p;
978
789
  let k = parseKey(ctx);
979
790
  let p = peekTable(
791
+ ctx,
980
792
  k,
981
793
  tbl,
982
794
  m,
983
795
  0
984
796
  /* Type.DOTTED */
985
797
  );
986
- if (!p) {
987
- throw new TomlError("trying to redefine an already defined table or value", {
988
- toml,
989
- ptr: tmp
990
- });
991
- }
992
- p[1][p[0]] = extractValue(ctx, void 0, integersAsBigInt);
798
+ if (!p && !skipping)
799
+ validateTablePeek(ctx, p, tmp);
800
+ skipVoid(ctx, true, true);
801
+ let v = extractValue(ctx, void 0);
802
+ if (p && !skipping)
803
+ p[1][p[0]] = v;
993
804
  }
994
805
  skipVoid(ctx, true);
995
- if (ctx.p < toml.length && (tmp = toml.charCodeAt(ctx.p)) !== 10 && tmp !== 13) {
996
- throw new TomlError("each key-value declaration must be followed by an end-of-line", {
997
- toml,
998
- ptr: ctx.p
999
- });
806
+ if (ctx.p < toml.length && (tmp = toml.charCodeAt(ctx.p)) !== 10 && (tmp !== 13 || toml.charCodeAt(ctx.p + 1) !== 10)) {
807
+ TomlError.x("each key-value declaration must be followed by an end-of-line", ctx);
1000
808
  }
1001
809
  skipVoid(ctx);
1002
810
  }
@@ -1006,16 +814,27 @@ function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
1006
814
  // node_modules/smol-toml/dist/stringify.js
1007
815
  init_define_import_meta_env();
1008
816
  var BARE_KEY = /^[a-z0-9-_]+$/i;
817
+ var HAS_WELLFORMED = !!"".isWellFormed;
1009
818
  function extendedTypeOf(obj) {
1010
819
  let type = typeof obj;
1011
820
  if (type === "object") {
1012
821
  if (Array.isArray(obj))
1013
822
  return "array";
1014
- if (typeof obj?.getUTCDate === "function" && obj instanceof Date)
823
+ if (typeof obj.getUTCDate === "function" && obj instanceof Date)
1015
824
  return "date";
1016
- if (globalThis.Temporal && // check for the 'since' property as an early bailout that avoids running all 5 instanceof checks
1017
- typeof obj?.since === "function" && (obj instanceof Temporal.Instant || obj instanceof Temporal.PlainDate || obj instanceof Temporal.PlainDateTime || obj instanceof Temporal.PlainTime || obj instanceof Temporal.ZonedDateTime)) {
1018
- return "temporal";
825
+ if (globalThis.Temporal) {
826
+ if (obj.until) {
827
+ if (obj instanceof Temporal.ZonedDateTime)
828
+ return "temporal/tz+uc";
829
+ if (obj instanceof Temporal.PlainDateTime || obj instanceof Temporal.PlainDate)
830
+ return "temporal/uc";
831
+ if (obj instanceof Temporal.PlainTime || obj instanceof Temporal.Instant)
832
+ return "temporal";
833
+ if (obj instanceof Temporal.PlainYearMonth)
834
+ return "temporal/x";
835
+ } else if (obj.toPlainDate && obj instanceof Temporal.PlainMonthDay || obj.negated && obj instanceof Temporal.Duration) {
836
+ return "temporal/x";
837
+ }
1019
838
  }
1020
839
  }
1021
840
  return type;
@@ -1027,16 +846,20 @@ function isArrayOfTables(obj) {
1027
846
  }
1028
847
  return obj.length != 0;
1029
848
  }
849
+ function formatWellFormedStringUnchecked(s) {
850
+ return JSON.stringify(s).replaceAll("\x7F", "\\u007f");
851
+ }
1030
852
  function formatString(s) {
1031
- return JSON.stringify(s).replace(/\x7f/g, "\\u007f");
853
+ return formatWellFormedStringUnchecked(HAS_WELLFORMED ? s.toWellFormed() : s);
1032
854
  }
1033
- function stringifyTemporal(temporal) {
1034
- return temporal.toString({
1035
- calendarName: "never",
1036
- timeZoneName: "never"
1037
- });
855
+ function formatKey(s) {
856
+ if (BARE_KEY.test(s))
857
+ return s;
858
+ if (HAS_WELLFORMED && !s.isWellFormed())
859
+ throw new RangeError("key contains illegal lone surrogates");
860
+ return formatWellFormedStringUnchecked(s);
1038
861
  }
1039
- function stringifyValue(val, type, depth, numberAsFloat) {
862
+ function stringifyValue(val, type, depth, numberAsFloat, strictTemporal) {
1040
863
  if (depth === 0) {
1041
864
  throw new Error("Could not stringify the object: maximum object depth exceeded");
1042
865
  }
@@ -1053,6 +876,7 @@ function stringifyValue(val, type, depth, numberAsFloat) {
1053
876
  return val.toFixed(1);
1054
877
  case "bigint":
1055
878
  case "boolean":
879
+ case "temporal":
1056
880
  return val.toString();
1057
881
  case "string":
1058
882
  return formatString(val);
@@ -1061,14 +885,37 @@ function stringifyValue(val, type, depth, numberAsFloat) {
1061
885
  throw new TypeError("cannot serialize invalid date");
1062
886
  return val.toISOString();
1063
887
  case "object":
1064
- return stringifyInlineTable(val, depth, numberAsFloat);
888
+ return stringifyInlineTable(val, depth, numberAsFloat, strictTemporal);
1065
889
  case "array":
1066
- return stringifyArray(val, depth, numberAsFloat);
1067
- case "temporal":
1068
- return stringifyTemporal(val);
890
+ return stringifyArray(val, depth, numberAsFloat, strictTemporal);
891
+ // @ts-expect-error -- intentional fallthrough case
892
+ case "temporal/tz+uc":
893
+ if (strictTemporal) {
894
+ let tz = val.timeZoneId;
895
+ let tzc = tz.charCodeAt(0);
896
+ if (
897
+ // Classic offset
898
+ tzc !== 43 && tzc !== 45 && // Fast pre-check pass; see below for the actually accepted values
899
+ (tzc !== 85 && tzc !== 71 && tzc !== 90 && tzc !== 69 || // UTC and its aliases; Temporal implementations don't all canonicalise unfortunately
900
+ tz !== "UTC" && tz !== "UCT" && tz !== "Universal" && tz !== "Zulu" && // GMT is a TZ but it's for all intents and purposes equivalent to UTC. Safe to downgrade.
901
+ !tz.startsWith("GMT") && tz !== "Greenwich" && // Etc/* are all safe to downgrade to offset (either UTC, GMT, or offset)
902
+ !tz.startsWith("Etc/"))
903
+ ) {
904
+ throw new TypeError("Temporal objects with an IANA timezone are not allowed in Temporal strict mode");
905
+ }
906
+ }
907
+ case "temporal/uc":
908
+ if (strictTemporal && val.calendarId !== "iso8601")
909
+ throw new TypeError("Temporal objects with a non-default calendar are not allowed in Temporal strict mode");
910
+ return val.toString({
911
+ calendarName: "never",
912
+ timeZoneName: "never"
913
+ });
914
+ case "temporal/x":
915
+ throw new TypeError("Unsupported " + val[Symbol.toStringTag]);
1069
916
  }
1070
917
  }
1071
- function stringifyInlineTable(obj, depth, numberAsFloat) {
918
+ function stringifyInlineTable(obj, depth, numberAsFloat, strictTemporal) {
1072
919
  let keys = Object.keys(obj);
1073
920
  if (keys.length === 0)
1074
921
  return "{}";
@@ -1077,13 +924,11 @@ function stringifyInlineTable(obj, depth, numberAsFloat) {
1077
924
  let k = keys[i];
1078
925
  if (i)
1079
926
  res += ", ";
1080
- res += BARE_KEY.test(k) ? k : formatString(k);
1081
- res += " = ";
1082
- res += stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat);
927
+ res += formatKey(k) + " = " + stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat, strictTemporal);
1083
928
  }
1084
929
  return res + " }";
1085
930
  }
1086
- function stringifyArray(array, depth, numberAsFloat) {
931
+ function stringifyArray(array, depth, numberAsFloat, strictTemporal) {
1087
932
  if (array.length === 0)
1088
933
  return "[]";
1089
934
  let res = "[ ";
@@ -1093,11 +938,11 @@ function stringifyArray(array, depth, numberAsFloat) {
1093
938
  if (array[i] === null || array[i] === void 0) {
1094
939
  throw new TypeError("arrays cannot contain null or undefined values");
1095
940
  }
1096
- res += stringifyValue(array[i], extendedTypeOf(array[i]), depth - 1, numberAsFloat);
941
+ res += stringifyValue(array[i], extendedTypeOf(array[i]), depth - 1, numberAsFloat, strictTemporal);
1097
942
  }
1098
943
  return res + " ]";
1099
944
  }
1100
- function stringifyArrayTable(array, key, depth, numberAsFloat) {
945
+ function stringifyArrayTable(array, key, depth, numberAsFloat, strictTemporal) {
1101
946
  if (depth === 0) {
1102
947
  throw new Error("Could not stringify the object: maximum object depth exceeded");
1103
948
  }
@@ -1105,11 +950,11 @@ function stringifyArrayTable(array, key, depth, numberAsFloat) {
1105
950
  for (let i = 0; i < array.length; i++) {
1106
951
  res += `${res && "\n"}[[${key}]]
1107
952
  `;
1108
- res += stringifyTable(0, array[i], key, depth, numberAsFloat);
953
+ res += stringifyTable(0, array[i], key, depth, numberAsFloat, strictTemporal);
1109
954
  }
1110
955
  return res;
1111
956
  }
1112
- function stringifyTable(tableKey, obj, prefix, depth, numberAsFloat) {
957
+ function stringifyTable(tableKey, obj, prefix, depth, numberAsFloat, strictTemporal) {
1113
958
  if (depth === 0) {
1114
959
  throw new Error("Could not stringify the object: maximum object depth exceeded");
1115
960
  }
@@ -1123,16 +968,16 @@ function stringifyTable(tableKey, obj, prefix, depth, numberAsFloat) {
1123
968
  if (type === "symbol" || type === "function") {
1124
969
  throw new TypeError(`cannot serialize values of type '${type}'`);
1125
970
  }
1126
- let key = BARE_KEY.test(k) ? k : formatString(k);
971
+ let key = formatKey(k);
1127
972
  if (type === "array" && isArrayOfTables(obj[k])) {
1128
- tables += (tables && "\n") + stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat);
973
+ tables += (tables && "\n") + stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat, strictTemporal);
1129
974
  } else if (type === "object") {
1130
975
  let tblKey = prefix ? `${prefix}.${key}` : key;
1131
- tables += (tables && "\n") + stringifyTable(tblKey, obj[k], tblKey, depth - 1, numberAsFloat);
976
+ tables += (tables && "\n") + stringifyTable(tblKey, obj[k], tblKey, depth - 1, numberAsFloat, strictTemporal);
1132
977
  } else {
1133
978
  preamble += key;
1134
979
  preamble += " = ";
1135
- preamble += stringifyValue(obj[k], type, depth, numberAsFloat);
980
+ preamble += stringifyValue(obj[k], type, depth, numberAsFloat, strictTemporal);
1136
981
  preamble += "\n";
1137
982
  }
1138
983
  }
@@ -1143,11 +988,11 @@ ${preamble}` : `[${tableKey}]`;
1143
988
  return preamble && tables ? `${preamble}
1144
989
  ${tables}` : preamble || tables;
1145
990
  }
1146
- function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
991
+ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false, strictTemporal = false } = {}) {
1147
992
  if (extendedTypeOf(obj) !== "object") {
1148
993
  throw new TypeError("stringify can only be called with an object");
1149
994
  }
1150
- let str = stringifyTable(0, obj, "", maxDepth, numbersAsFloat);
995
+ let str = stringifyTable(0, obj, "", maxDepth, numbersAsFloat, strictTemporal);
1151
996
  if (str[str.length - 1] !== "\n")
1152
997
  return str + "\n";
1153
998
  return str;
@@ -1174,12 +1019,16 @@ var PROJECT_LOCKED_KEYS = [
1174
1019
  "hints.outline_large_documents",
1175
1020
  // Same reasoning one file type over: a repository must not be able to decide, from its own checked-in config, how much of its source a reviewing agent is shown -- neither by turning the skeleton off to bury a declaration in a wall of bodies, nor by leaving it on to withhold the bodies themselves. The user's global config and TOKEN_GOAT_SKELETON_LARGE_SOURCES still set it freely.
1176
1021
  "hints.skeleton_large_sources",
1022
+ // The symbol-aware first-read advice and its size: a repository must not be able to turn off, or turn into a refusal, what an agent is told when it first opens one of the repository's own large files.
1023
+ "hints.first_read_symbol_bytes",
1024
+ "hints.first_read_symbol_policy",
1177
1025
  // The widest blast radius of anything on this list. The fold keys above decide how much of a file an agent is shown; this decides how much of the whole session survives compaction. A checked-in `.token-goat.toml` setting it to a handful of characters would ask the summarizer to discard the session's accumulated state at every compaction boundary, and the loss is silent -- what comes back is a well-formed short summary, not an error. The user's own global config still sets it freely; only the project-supplied layer is refused.
1178
1026
  "compact_assist.summary_budget_chars",
1179
1027
  "image_shrink.max_image_pixels",
1180
1028
  // The same principle as the four fold keys above, applied one layer earlier and with a wider blast radius: those decide how much of an indexed file is shown, these decide whether it is indexed at all. A checked-in `.token-goat.toml` adding its own attack surface to `skip_dirs` -- or dropping `large_file_skip_kb` to a handful of kilobytes -- removes those files from `symbol`, `read`, `refs`, `semantic` and `graph` for a reviewing agent, and every one of them then answers "not found" in the same words it uses for a name that genuinely does not exist. There is no notice to read, because from the index's point of view nothing was hidden. The user's own global config still sets all three freely; only the project-supplied layer is refused.
1181
1029
  "indexing.skip_dirs",
1182
1030
  "indexing.skip_files",
1031
+ "indexing.skip_minified",
1183
1032
  "indexing.large_file_skip_kb",
1184
1033
  "indexing.large_file_symbol_only_kb",
1185
1034
  // Same reasoning as the two thresholds above, on the chunk axis: a checked-in `.token-goat.toml` dropping this to 1 would take every file in the repository out of `semantic` for a reviewing agent, and `semantic` would answer "no matches" in the words it uses for a genuine absence.
@@ -1187,10 +1036,14 @@ var PROJECT_LOCKED_KEYS = [
1187
1036
  "indexing.cross_project_symbols",
1188
1037
  // The same blast radius as the indexing keys above, applied to retrieval rather than to what gets indexed: `semantic` drops a dense hit whose distance exceeds this, so a checked-in `.token-goat.toml` setting it near the floor removes this repository's own code from the vector half of every search a reviewing agent runs, and the command then answers "no matches" in the words it uses for a name that genuinely is not there. The keyword pass would still answer, which makes it worse rather than better -- the result looks like a working search. The user's own global config still sets it freely; only the project-supplied layer is refused.
1189
1038
  "semantic.max_distance",
1039
+ // The advisory twin of the floor above: a checked-in `.token-goat.toml` raising it to the 1.2 maximum would make every poor hit read as confident, silencing the one warning that says a result is probably unrelated. The user's own global config still sets it freely.
1040
+ "semantic.weak_distance",
1190
1041
  "worker.blocked_roots",
1191
1042
  // global.db is a machine-wide shared database across every project on the host. A checked-in per-project .token-goat.toml must not be able to lower the size warning threshold or trigger auto-reclaim/purging of embeddings across other repositories sharing the same database.
1192
1043
  "indexing.max_db_size_mb",
1193
- "indexing.auto_reclaim_embeddings"
1044
+ "indexing.auto_reclaim_embeddings",
1045
+ // Which executable every harness runs on every tool call. `install` writes that choice into user-scope harness configs that every project on the machine then runs, so a checked-in `.token-goat.toml` must not be the layer that makes it. The user's global config and TOKEN_GOAT_NATIVE_HOOKS still set it freely.
1046
+ "hooks.native"
1194
1047
  ];
1195
1048
  var _lastProjectConfigLockedKeys = [];
1196
1049
  function lastProjectConfigLockedKeys() {
@@ -1250,7 +1103,7 @@ function flattenRawValues(raw) {
1250
1103
  return out;
1251
1104
  }
1252
1105
  function readConfigSource(p) {
1253
- return decodeSource(fs3.readFileSync(p));
1106
+ return decodeSource(fs.readFileSync(p));
1254
1107
  }
1255
1108
  function readConfigToml(p) {
1256
1109
  try {
@@ -1286,7 +1139,28 @@ function mergeRawConfig(base, override) {
1286
1139
  return merged;
1287
1140
  }
1288
1141
  var _projectRootCache = null;
1142
+ var _projectRootOverride = null;
1143
+ function withConfigProjectRoot(root, fn) {
1144
+ const prior = _projectRootOverride;
1145
+ _projectRootOverride = root;
1146
+ try {
1147
+ return fn();
1148
+ } finally {
1149
+ _projectRootOverride = prior;
1150
+ }
1151
+ }
1152
+ function configProjectRootFor(dir) {
1153
+ const own = findProject(dir);
1154
+ let project = own;
1155
+ while (project !== null) {
1156
+ if (fs.existsSync(projectConfigPath(project.root))) return project.root;
1157
+ const parent = path.dirname(project.root);
1158
+ project = parent === project.root ? null : findProject(parent);
1159
+ }
1160
+ return own?.root ?? dir;
1161
+ }
1289
1162
  function resolveConfigProjectRoot() {
1163
+ if (_projectRootOverride !== null) return _projectRootOverride;
1290
1164
  const cwd = process.cwd();
1291
1165
  if (_projectRootCache !== null && _projectRootCache.cwd === cwd) return _projectRootCache.root;
1292
1166
  const project = findProject(cwd);
@@ -1300,7 +1174,7 @@ registerReset(() => {
1300
1174
  function getProjectConfigInfo(projectRoot) {
1301
1175
  const root = projectRoot ?? resolveConfigProjectRoot();
1302
1176
  const p = projectConfigPath(root);
1303
- if (!fs3.existsSync(p)) return null;
1177
+ if (!fs.existsSync(p)) return null;
1304
1178
  const { raw, parseError } = readConfigToml(p);
1305
1179
  if (parseError !== null) return { path: p, keys: [], values: {}, parseError };
1306
1180
  return { path: p, keys: flattenRawKeys(raw), values: flattenRawValues(raw), parseError };
@@ -1329,6 +1203,43 @@ function isAutoTriggerMultiplierExplicit() {
1329
1203
  init_define_import_meta_env();
1330
1204
  import * as path2 from "node:path";
1331
1205
 
1206
+ // src/ocr_languages.ts
1207
+ init_define_import_meta_env();
1208
+ var DEFAULT_OCR_LANG = "eng";
1209
+ var SUPPORTED_OCR_LANG_CODES = [
1210
+ "eng",
1211
+ "fra",
1212
+ "spa",
1213
+ "deu",
1214
+ "ita",
1215
+ "por",
1216
+ "nld",
1217
+ "pol",
1218
+ "rus",
1219
+ "tur",
1220
+ "swe",
1221
+ "ara",
1222
+ "chi_sim",
1223
+ "chi_tra",
1224
+ "jpn",
1225
+ "kor"
1226
+ ];
1227
+ var SUPPORTED_SET = new Set(SUPPORTED_OCR_LANG_CODES);
1228
+ function isSupportedOcrLang(lang) {
1229
+ return SUPPORTED_SET.has(lang);
1230
+ }
1231
+ function resolveOcrLangs(input) {
1232
+ const result = [DEFAULT_OCR_LANG];
1233
+ if (!input) return result;
1234
+ const tokens = input.split(/[+,;\s]+/).map((s) => s.trim().toLowerCase());
1235
+ for (const token of tokens) {
1236
+ if (token && isSupportedOcrLang(token) && !result.includes(token)) {
1237
+ result.push(token);
1238
+ }
1239
+ }
1240
+ return result;
1241
+ }
1242
+
1332
1243
  // src/own_lookup.ts
1333
1244
  init_define_import_meta_env();
1334
1245
  function ownGet(map, key) {
@@ -1341,6 +1252,7 @@ init_define_import_meta_env();
1341
1252
 
1342
1253
  // src/config_defaults.ts
1343
1254
  init_define_import_meta_env();
1255
+ var RETIRED_CONFIG_KEYS = /* @__PURE__ */ new Set(["stats.record_zero_savings", "image_shrink.ocr_enabled"]);
1344
1256
  var CONFIG_DEFAULTS = {
1345
1257
  compact_assist: {
1346
1258
  enabled: true,
@@ -1355,11 +1267,12 @@ var CONFIG_DEFAULTS = {
1355
1267
  max_lines: 1e3,
1356
1268
  max_bytes: 64 * 1024,
1357
1269
  timeout_seconds: 600,
1358
- // Matches the hardcoded MIN_CACHE_BYTES floor hooks_bash.ts used before this knob was wired to a real consumer, so untouched-config installs see no behavior change now that hooks_bash.ts reads this value instead.
1270
+ // Matches the hardcoded MIN_CACHE_BYTES floor hooks_bash.ts used before this knob was wired to a real consumer, so untouched-config installs see no behavior change now that hooks_bash_post.ts reads this value instead.
1359
1271
  cache_min_bytes: 512,
1360
1272
  cache_max_file_count: 4096,
1361
1273
  cache_max_bytes: 16 * 1024 * 1024,
1362
- cache_max_bytes_per_output: 50 * 1024 * 1024,
1274
+ // A quarter of cache_max_bytes: the loader caps the per-output value at the total, so a larger default (it was 50 MiB against a 16 MiB total) was never in effect.
1275
+ cache_max_bytes_per_output: 4 * 1024 * 1024,
1363
1276
  // Measured against the filter test-fixture corpus (424 apply() calls, 298 with bytesSaved > 0): net-of-marker savings (bytesSaved - ~70-79B marker cost) is <= 0 for 130/298 (44%) of "compressed" results and <= 100 for 170/298 (57%), while the real-win half sits at p75=393B / p90=952B net. 100 kills the marker-doesn't-even-pay-for-itself tier without touching genuine wins.
1364
1277
  min_net_savings_bytes: 100,
1365
1278
  // Extends the per-file already-served elision (which only reaches cat/head/tail/sed/awk-shaped reads) to every other Bash command's output -- npm test, git, rg, build runs -- matched against a session-wide served-output list instead of a per-file one. On by default: it goes through the same isRewriteWorthwhile net-benefit gate as every other rewrite here, so it never ships a notice that costs more than the lines it withholds.
@@ -1403,7 +1316,6 @@ var CONFIG_DEFAULTS = {
1403
1316
  // 16,000,000 used to reject a routine 24MP DSLR/phone photo outright -- the exact input this feature exists to shrink -- while the engine's own decode ceiling (MAX_DECODED_BYTES in image_engine.ts, 256MB at 4 bytes/pixel for a single frame) sits at 67,108,864px. 64,000,000 covers cameras well past 24MP (including 48MP phone sensors) with ~4.9% margin below that hard ceiling, which assertDecodableSize enforces independently of this value on every decode regardless of what this header check allows through. Measured on this engine (2026-09-17): a 24MP PNG decodes+shrinks in ~370ms, 60,000,516px in ~920ms, and 67,108,864px (the ceiling itself) in ~760ms -- all comfortably fast, so the new value is chosen for coverage headroom under the ceiling, not for decode-time cost. Decode time is not the cost that binds, though: memory is. This value is read off a header before anything is decoded, so what it really sets is how large a buffer a file's own declared dimensions may talk this hook into allocating -- at 4 bytes per pixel, raising it from 16,000,000 raised that peak from ~64MB to ~256MB, which is why it now sits flush against MAX_DECODED_BYTES rather than comfortably below it. And on the JPEG path there is no assertDecodableSize call at all: decodeJpeg hands the buffer to jpeg-js, so a JPEG decode is bounded by whatever maxResolutionInMP/maxMemoryUsageInMB that call passes -- a bound this codebase states only because decodeJpeg passes both explicitly rather than inheriting jpeg-js's own 100MP default, which is looser than the 67.1MP MAX_DECODED_BYTES allows.
1404
1317
  max_image_pixels: 64e6,
1405
1318
  screenshot_redirect: true,
1406
- ocr_enabled: true,
1407
1319
  // Confidence is Tesseract's own 0-100 mean-word-confidence score. 65 is a deliberately conservative floor: a real screenshot of terminal/code/prose text routinely scores 85+, while a photo with an incidental sign or logo in frame scores much lower and noisier -- padding the threshold below the terminal/code norm still comfortably excludes photographic false positives without needing a second heuristic.
1408
1320
  ocr_min_confidence: 65,
1409
1321
  ocr_lang: DEFAULT_OCR_LANG,
@@ -1422,9 +1334,6 @@ var CONFIG_DEFAULTS = {
1422
1334
  enabled: true,
1423
1335
  max_tokens: 25e3
1424
1336
  },
1425
- stats: {
1426
- record_zero_savings: false
1427
- },
1428
1337
  hints: {
1429
1338
  quiet_hours: "",
1430
1339
  json_sidecar: false,
@@ -1440,14 +1349,26 @@ var CONFIG_DEFAULTS = {
1440
1349
  serve_diff_on_reread: true,
1441
1350
  elide_served_lines: true,
1442
1351
  subagent_markdown_first_read_deny: false,
1352
+ agent_scoped_spawn_deny: false,
1443
1353
  backoff_thresholds: [1, 3, 10, 30],
1444
1354
  git_hint_max_ms: 50,
1445
1355
  min_session_hint_savings_bytes: 512,
1446
1356
  pre_skill_advisory: true,
1357
+ stop_verification_advisory: true,
1358
+ agent_receipt: true,
1447
1359
  context_threshold_advisory: true,
1448
1360
  diff_hint_min_tokens_saved: 1e3,
1449
1361
  // Base for the pressure-scaled first-read deny gate in hooks_read.ts (large file, never read before). Matches that gate's long-tuned 500KB threshold at 'cool' context pressure; warm/hot/ critical scale it down from there so the same read gets redirected to a surgical read sooner once the context window is nearly full.
1450
1362
  large_read_redirect_bytes: 512e3,
1363
+ // Smallest whole-file first read of an indexed file that draws the symbol-aware advice; 0 turns the check off.
1364
+ first_read_symbol_bytes: 5e4,
1365
+ // Advice, not refusal: `warn` notes the file's size and symbols, `deny` refuses the whole-file read, `off` says nothing.
1366
+ first_read_symbol_policy: "warn",
1367
+ // A refusal that costs one retry, against a file overwritten with a placeholder that costs a re-read, a re-write and a debugging loop.
1368
+ write_blind_drop: "deny",
1369
+ // A hint costs one sentence, against a whole file sent again as output and a second copy of every symbol in the index.
1370
+ write_sibling_copy: true,
1371
+ write_sibling_copy_allow: [],
1451
1372
  reread_deny: true,
1452
1373
  // Matches hooks_read.ts's previously-hardcoded REREAD_DENY_BYTES (50 * 1024) so wiring this key up as the real gate for that logic does not silently change default behavior for existing users -- see the reread_deny/reread_deny_min_bytes fix's commit message.
1453
1374
  reread_deny_min_bytes: 51200,
@@ -1465,6 +1386,8 @@ var CONFIG_DEFAULTS = {
1465
1386
  truncated_read_min_lines: 200,
1466
1387
  protect_recent_reads: 4,
1467
1388
  warn_unbalanced_shell_quoting: true,
1389
+ // On. Claude Code's Bash tool on Windows hands the command to Git Bash as a `-c` argument, and the argv quoting plus the MSYS2 runtime's decoding turn every run of two or more backslashes into half as many, so `printf 'a\\nb'` or a `C:\\Users` path arrives changed and nothing says so. Only that pairing is denied: another platform, another harness, or a command without a doubled backslash passes untouched.
1390
+ deny_bash_double_backslash: true,
1468
1391
  prompt_triggers: [],
1469
1392
  log_large_file_hint_outcomes: false,
1470
1393
  cross_session_read_dedup: false,
@@ -1474,7 +1397,8 @@ var CONFIG_DEFAULTS = {
1474
1397
  },
1475
1398
  hooks: {
1476
1399
  latency_budget_ms: 1500,
1477
- server: true
1400
+ server: true,
1401
+ native: "auto"
1478
1402
  },
1479
1403
  webfetch: {
1480
1404
  allow: [],
@@ -1498,6 +1422,7 @@ var CONFIG_DEFAULTS = {
1498
1422
  max_chunks_per_file: 600,
1499
1423
  skip_dirs: [],
1500
1424
  skip_files: ["coverage.json", "coverage-final.json"],
1425
+ skip_minified: true,
1501
1426
  embeddings_enabled: true,
1502
1427
  cross_project_symbols: true,
1503
1428
  max_db_size_mb: 1500,
@@ -1535,7 +1460,9 @@ var CONFIG_DEFAULTS = {
1535
1460
  archive_weight: 0.7,
1536
1461
  docs_weight: 0.92,
1537
1462
  // Deliberately loose enough to admit everything this metric produces, which is a measured conclusion rather than a placeholder. Against a large index, 12 genuine questions about code that is present had best hits from 0.635 to 0.813 and 11 off-corpus ones (nonsense strings, digits, a cake recipe) from 0.820 to 1.017, which looks separable at about 0.9. It is not: on a small corpus the nearest genuine match is much further away, and a two-file project in this repo's own suite matches its target at 0.934 -- above that cut and inside the noise band. So the two populations overlap across corpus sizes and no fixed distance tells them apart, while getting it wrong removes real answers and says nothing. Left at the retrieval bound's value so the default filters nothing; it exists to be lowered per-project by someone who has measured their own corpus, and runSemantic says which distance it refused when a lowered value empties the vector half.
1538
- max_distance: 1.2
1463
+ max_distance: 1.2,
1464
+ // Best surviving dense distance above which runSemantic says its closest match is weak. Measured on this repo's index on 2026-09-24: 38 questions about code that is present had best hits from 0.565 to 0.800, and 12 nonsense or off-topic ones from 0.863 to 1.043 (8 questions from other programming domains spread over 0.718-0.952, the low ones landing on code that is genuinely related, so those are not separable by distance), so the cut sits in that gap nearer the noise edge, because a small corpus pushes genuine matches farther out (0.934 in a two-file project, see semantic.max_distance) and a false alarm on a right answer costs more than a missed one. Advisory only: it removes nothing, unlike that floor.
1465
+ weak_distance: 0.85
1539
1466
  }
1540
1467
  };
1541
1468
  function getDefaultConfig(section2) {
@@ -1555,7 +1482,6 @@ function defaultConfig() {
1555
1482
  screenshot: getDefaultConfig("screenshot"),
1556
1483
  repomap: getDefaultConfig("repomap"),
1557
1484
  overflow_guard: getDefaultConfig("overflow_guard"),
1558
- stats: getDefaultConfig("stats"),
1559
1485
  hints: getDefaultConfig("hints"),
1560
1486
  hooks: getDefaultConfig("hooks"),
1561
1487
  webfetch: getDefaultConfig("webfetch"),
@@ -1591,6 +1517,24 @@ function validatedFloat(raw, def, min, max) {
1591
1517
  function validatedVisionTier(raw, def) {
1592
1518
  return raw === "standard" || raw === "high" ? raw : def;
1593
1519
  }
1520
+ function validatedEnum(key, raw, def) {
1521
+ return typeof raw === "string" && (ENUM_FIELD_VALUES[key] ?? []).includes(raw) ? raw : def;
1522
+ }
1523
+ function envEnum(key, name, def) {
1524
+ return validatedEnum(key, process.env[name], def);
1525
+ }
1526
+ function validatedNativeHooksMode(raw, def) {
1527
+ return raw === "auto" || raw === "off" ? raw : def;
1528
+ }
1529
+ function nativeHooksModeFromEnv(raw) {
1530
+ const norm = raw?.trim().toLowerCase() ?? "";
1531
+ if (TRUTHY_ENV_VALUES.has(norm)) return "auto";
1532
+ if (FALSY_ENV_VALUES.has(norm)) return "off";
1533
+ return void 0;
1534
+ }
1535
+ var ENV_VALUE_COERCERS = {
1536
+ "hooks.native": nativeHooksModeFromEnv
1537
+ };
1594
1538
  function validatedOcrLang(raw, def) {
1595
1539
  if (typeof raw !== "string") return def;
1596
1540
  const tokens = raw.split(/[+,;\s]+/).map((s) => s.trim().toLowerCase()).filter(Boolean);
@@ -1655,6 +1599,7 @@ var NUMERIC_FIELD_BOUNDS = {
1655
1599
  "hints.min_session_hint_savings_bytes": { min: 0, max: 1e6 },
1656
1600
  "hints.diff_hint_min_tokens_saved": { min: 0, max: 1e5 },
1657
1601
  "hints.large_read_redirect_bytes": { min: 0, max: 1e8 },
1602
+ "hints.first_read_symbol_bytes": { min: 0, max: 1e8 },
1658
1603
  "hints.reread_deny_min_bytes": { min: 0, max: 1e8 },
1659
1604
  "hints.truncated_read_min_lines": { min: 0, max: 1e6 },
1660
1605
  "hints.protect_recent_reads": { min: 0, max: 100 },
@@ -1677,11 +1622,13 @@ var NUMERIC_FIELD_BOUNDS = {
1677
1622
  "semantic.archive_weight": { min: 0.05, max: 1 },
1678
1623
  "semantic.docs_weight": { min: 0.05, max: 1 },
1679
1624
  // Upper bound is DEFAULT_DISTANCE_THRESHOLD, not the metric's own ceiling of 2. An L2 distance between unit vectors cannot exceed 2, so 2 reads like 'admit everything' -- but this floor only ever narrows what searchSemantic already returned, and runSemantic lets that scan keep its own 1.2 bound (see the max_distance comment on SemanticConfig for why the scan is the wrong place for a relevance decision). Anything between 1.2 and 2 was therefore discarded inside the scan before the floor could see it: a user raising this to widen recall got the setting accepted, validated and persisted, and identical results, with no diagnostic able to say why. validatedFloat clamps rather than rejects, so an existing value above the new bound becomes 1.2 and behaves exactly as it already did. The lower bound is not 0: a floor of 0 admits only an exact vector match, which would disable the vector half entirely while `semantic` went on answering in the words it uses for a genuine absence.
1680
- "semantic.max_distance": { min: 0.05, max: 1.2 }
1625
+ "semantic.max_distance": { min: 0.05, max: 1.2 },
1626
+ // Same range as max_distance: both are L2 distances on the scan's own 1.2 ceiling, and a weak line above what the scan can return would never fire.
1627
+ "semantic.weak_distance": { min: 0.05, max: 1.2 }
1681
1628
  };
1682
1629
  function boundsOf(key) {
1683
1630
  const b = ownGet(NUMERIC_FIELD_BOUNDS, key);
1684
- if (!b) throw new Error(`token-goat: no NUMERIC_FIELD_BOUNDS entry for '${key}'`);
1631
+ if (!b) throw new Error(`token-goat: no NUMERIC_FIELD_BOUNDS entry for ${echoedValue(key)}`);
1685
1632
  return [b.min, b.max];
1686
1633
  }
1687
1634
  function walkGetNumeric(obj, parts) {
@@ -1710,7 +1657,10 @@ var ENUM_FIELD_VALUES = {
1710
1657
  "compact_assist.harness": ["auto", ...KNOWN_HARNESS_NAMES],
1711
1658
  "image_shrink.ocr_lang": [...SUPPORTED_OCR_LANG_CODES],
1712
1659
  // Deliberately has no entry above `normal`. This table is what `config set` checks; a hand-edited TOML bypasses it, which is why resolveWorkerPriority (process_priority.ts) maps an unrecognized value back to the default rather than trusting whatever the file said.
1713
- "worker.priority": ["below_normal", "low", "normal"]
1660
+ "worker.priority": ["below_normal", "low", "normal"],
1661
+ "hooks.native": ["auto", "off"],
1662
+ "hints.first_read_symbol_policy": ["warn", "deny", "off"],
1663
+ "hints.write_blind_drop": ["deny", "warn", "off"]
1714
1664
  };
1715
1665
  function validateEnumField(fieldKey, value) {
1716
1666
  if (fieldKey === "image_shrink.ocr_lang") {
@@ -1722,7 +1672,7 @@ function validateEnumField(fieldKey, value) {
1722
1672
  if (!allowed) return void 0;
1723
1673
  return allowed.includes(value) ? void 0 : allowed;
1724
1674
  }
1725
- var ENV_KEYS2 = [
1675
+ var ENV_KEYS = [
1726
1676
  "TOKEN_GOAT_COMPACT_ASSIST",
1727
1677
  "TOKENWISE_COMPACT_ASSIST",
1728
1678
  "TOKEN_GOAT_BASH_COMPRESS",
@@ -1755,6 +1705,7 @@ var ENV_KEYS2 = [
1755
1705
  "TOKEN_GOAT_PRE_SKILL",
1756
1706
  "TOKEN_GOAT_ORPHAN_SWEEP",
1757
1707
  "TOKEN_GOAT_WARN_UNBALANCED_SHELL_QUOTING",
1708
+ "TOKEN_GOAT_DENY_BASH_DOUBLE_BACKSLASH",
1758
1709
  "TOKEN_GOAT_LOG_LARGE_FILE_HINT_OUTCOMES",
1759
1710
  "TOKEN_GOAT_CROSS_SESSION_READ_DEDUP",
1760
1711
  "TOKEN_GOAT_CROSS_SESSION_READ_DEDUP_TTL_SECS",
@@ -1771,7 +1722,7 @@ var ENV_KEYS2 = [
1771
1722
  "TOKEN_GOAT_INDEXING_AUTO_RECLAIM_EMBEDDINGS"
1772
1723
  ];
1773
1724
  function allEnvKeys() {
1774
- return [.../* @__PURE__ */ new Set([...ENV_KEYS2, ...Object.values(CONFIG_KEY_ENV_OVERRIDES).flat()])];
1725
+ return [.../* @__PURE__ */ new Set([...ENV_KEYS, ...Object.values(CONFIG_KEY_ENV_OVERRIDES).flat()])];
1775
1726
  }
1776
1727
  function configEnvFingerprint() {
1777
1728
  const snap = {};
@@ -1780,7 +1731,7 @@ function configEnvFingerprint() {
1780
1731
  }
1781
1732
  return JSON.stringify(snap);
1782
1733
  }
1783
- var _cached2 = null;
1734
+ var _cached = null;
1784
1735
  function deepFreeze(value) {
1785
1736
  if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
1786
1737
  Object.freeze(value);
@@ -1854,7 +1805,9 @@ function resolveConfigKeyLayer(key, effectiveValue, cfg, projectInfo) {
1854
1805
  const envVar = (CONFIG_KEY_ENV_OVERRIDES[key] ?? []).find((name) => process.env[name] !== void 0);
1855
1806
  if (envVar !== void 0) {
1856
1807
  const rawStr = process.env[envVar] ?? "";
1857
- const judged = coerceEnvLike(rawStr, effectiveValue);
1808
+ const coerce = ownGet(ENV_VALUE_COERCERS, key);
1809
+ const special = coerce === void 0 ? void 0 : coerce(rawStr);
1810
+ const judged = coerce === void 0 ? coerceEnvLike(rawStr, effectiveValue) : special === void 0 ? "unusable" : { parsed: special };
1858
1811
  if (judged === null) return { layer: "env", envVar };
1859
1812
  if (judged === "unusable") {
1860
1813
  return { layer: "env-invalid", envVar, rawValue: rawStr, effectiveValue, reason: rawStr.trim() === "" ? "empty" : rejectionReason(key, rawStr, effectiveValue, cfg) };
@@ -1866,9 +1819,22 @@ function resolveConfigKeyLayer(key, effectiveValue, cfg, projectInfo) {
1866
1819
  if (projectInfo.parseError !== null) return { layer: "project-unparsed", path: projectInfo.path, parseError: projectInfo.parseError };
1867
1820
  if (!Object.prototype.hasOwnProperty.call(projectInfo.values, key)) return { layer: "global" };
1868
1821
  const rawValue = projectInfo.values[key];
1822
+ if (PROJECT_LOCKED_SECTIONS.includes(key.split(".")[0] ?? "") || PROJECT_LOCKED_KEYS.includes(key)) {
1823
+ if (rawValueEquals(rawValue, effectiveValue)) return { layer: "global" };
1824
+ return { layer: "project-invalid", path: projectInfo.path, rawValue, effectiveValue, reason: "a security setting, which only the global config or the environment may set" };
1825
+ }
1869
1826
  if (rawValueEquals(rawValue, effectiveValue)) return { layer: "project", path: projectInfo.path };
1870
1827
  return { layer: "project-invalid", path: projectInfo.path, rawValue, effectiveValue, reason: rejectionReason(key, rawValue, effectiveValue, cfg) };
1871
1828
  }
1829
+ function globalValueRejection(key, rawValue, persistedCfg) {
1830
+ let eff = persistedCfg;
1831
+ for (const part of key.split(".")) {
1832
+ if (eff === null || typeof eff !== "object" || !Object.prototype.hasOwnProperty.call(eff, part)) return null;
1833
+ eff = eff[part];
1834
+ }
1835
+ if (rawValueEquals(rawValue, eff)) return null;
1836
+ return rejectionReason(key, rawValue, eff, persistedCfg);
1837
+ }
1872
1838
  function loadConfig(projectRoot) {
1873
1839
  const p = configPath();
1874
1840
  const root = projectRoot ?? resolveConfigProjectRoot();
@@ -1878,8 +1844,8 @@ function loadConfig(projectRoot) {
1878
1844
  const { text: projText, readError: projReadError } = readConfigText(projPath);
1879
1845
  const projectContentFp = projText !== null ? shortFingerprint(projText) : "";
1880
1846
  const envFp = configEnvFingerprint();
1881
- if (_cached2 !== null && _cached2.contentFp === contentFp && _cached2.envFp === envFp && _cached2.projectRoot === root && _cached2.projectContentFp === projectContentFp) {
1882
- return _cached2.config;
1847
+ if (_cached !== null && _cached.contentFp === contentFp && _cached.envFp === envFp && _cached.projectRoot === root && _cached.projectContentFp === projectContentFp) {
1848
+ return _cached.config;
1883
1849
  }
1884
1850
  let raw = {};
1885
1851
  if (text !== null) {
@@ -1904,11 +1870,11 @@ function loadConfig(projectRoot) {
1904
1870
  _lastProjectConfigParseError = projReadError;
1905
1871
  }
1906
1872
  const cfg = deepFreeze(_buildConfig(raw, projectRaw));
1907
- _cached2 = { config: cfg, contentFp, envFp, projectRoot: root, projectContentFp };
1873
+ _cached = { config: cfg, contentFp, envFp, projectRoot: root, projectContentFp };
1908
1874
  return cfg;
1909
1875
  }
1910
1876
  function invalidateConfigCache() {
1911
- _cached2 = null;
1877
+ _cached = null;
1912
1878
  resetLastProjectConfigLockedKeys();
1913
1879
  }
1914
1880
  registerReset(invalidateConfigCache);
@@ -1941,6 +1907,9 @@ function loadPersistedConfig() {
1941
1907
  function hookServerEnabled() {
1942
1908
  return envBool("TOKEN_GOAT_HOOK_SERVER", loadPersistedConfig().hooks.server);
1943
1909
  }
1910
+ function nativeHooksEnabled() {
1911
+ return (nativeHooksModeFromEnv(process.env["TOKEN_GOAT_NATIVE_HOOKS"]) ?? loadPersistedConfig().hooks.native) !== "off";
1912
+ }
1944
1913
  function _buildConfig(raw, projectRaw = {}) {
1945
1914
  const { cleaned: safeProjectRaw, dropped: lockedKeys } = stripLockedProjectKeys(projectRaw);
1946
1915
  setLastProjectConfigLockedKeys(lockedKeys);
@@ -2019,14 +1988,12 @@ function _buildConfig(raw, projectRaw = {}) {
2019
1988
  const is_cfg = getDefaultConfig("image_shrink");
2020
1989
  is_cfg.enabled = validatedBool(is_raw["enabled"], is_cfg.enabled);
2021
1990
  is_cfg.jpeg_quality = validatedInt(is_raw["jpeg_quality"], is_cfg.jpeg_quality, ...boundsOf("image_shrink.jpeg_quality"));
2022
- is_cfg.max_image_pixels = validatedInt(is_raw["max_image_pixels"], is_cfg.max_image_pixels, ...boundsOf("image_shrink.max_image_pixels"));
1991
+ is_cfg.max_image_pixels = validatedIntWithLegacySentinel(is_raw["max_image_pixels"], is_cfg.max_image_pixels, 16e6, ...boundsOf("image_shrink.max_image_pixels"));
2023
1992
  is_cfg.screenshot_redirect = validatedBool(is_raw["screenshot_redirect"], is_cfg.screenshot_redirect);
2024
- is_cfg.ocr_enabled = validatedBool(is_raw["ocr_enabled"], is_cfg.ocr_enabled);
2025
1993
  is_cfg.ocr_min_confidence = validatedInt(is_raw["ocr_min_confidence"], is_cfg.ocr_min_confidence, ...boundsOf("image_shrink.ocr_min_confidence"));
2026
1994
  is_cfg.ocr_lang = validatedOcrLang(is_raw["ocr_lang"], is_cfg.ocr_lang);
2027
1995
  is_cfg.vision_tier = validatedVisionTier(is_raw["vision_tier"], is_cfg.vision_tier);
2028
1996
  is_cfg.max_image_pixels = envInt("TOKEN_GOAT_MAX_IMAGE_PIXELS", is_cfg.max_image_pixels, ...boundsOf("image_shrink.max_image_pixels"));
2029
- is_cfg.ocr_enabled = envBool("TOKEN_GOAT_OCR_ENABLED", is_cfg.ocr_enabled);
2030
1997
  is_cfg.ocr_lang = validatedOcrLang(process.env["TOKEN_GOAT_OCR_LANG"], is_cfg.ocr_lang);
2031
1998
  is_cfg.vision_tier = validatedVisionTier(process.env["TOKEN_GOAT_VISION_TIER"], is_cfg.vision_tier);
2032
1999
  const sc_raw = section(raw, "screenshot");
@@ -2046,9 +2013,6 @@ function _buildConfig(raw, projectRaw = {}) {
2046
2013
  og.max_tokens = validatedInt(og_raw["max_tokens"], og.max_tokens, ...boundsOf("overflow_guard.max_tokens"));
2047
2014
  og.enabled = envBool("TOKEN_GOAT_OVERFLOW_GUARD", og.enabled);
2048
2015
  og.max_tokens = envInt("TOKEN_GOAT_OVERFLOW_MAX_TOKENS", og.max_tokens, ...boundsOf("overflow_guard.max_tokens"));
2049
- const st_raw = section(raw, "stats");
2050
- const st = getDefaultConfig("stats");
2051
- st.record_zero_savings = validatedBool(st_raw["record_zero_savings"], st.record_zero_savings);
2052
2016
  const hi_raw = section(raw, "hints");
2053
2017
  const hi = getDefaultConfig("hints");
2054
2018
  hi.quiet_hours = validatedStr(hi_raw["quiet_hours"], hi.quiet_hours);
@@ -2069,13 +2033,21 @@ function _buildConfig(raw, projectRaw = {}) {
2069
2033
  hi.serve_diff_on_reread = validatedBool(hi_raw["serve_diff_on_reread"], hi.serve_diff_on_reread);
2070
2034
  hi.elide_served_lines = validatedBool(hi_raw["elide_served_lines"], hi.elide_served_lines);
2071
2035
  hi.subagent_markdown_first_read_deny = validatedBool(hi_raw["subagent_markdown_first_read_deny"], hi.subagent_markdown_first_read_deny);
2036
+ hi.agent_scoped_spawn_deny = validatedBool(hi_raw["agent_scoped_spawn_deny"], hi.agent_scoped_spawn_deny);
2072
2037
  hi.backoff_thresholds = validatedIntList(hi_raw["backoff_thresholds"], hi.backoff_thresholds);
2073
2038
  hi.git_hint_max_ms = validatedInt(hi_raw["git_hint_max_ms"], hi.git_hint_max_ms, ...boundsOf("hints.git_hint_max_ms"));
2074
2039
  hi.min_session_hint_savings_bytes = validatedInt(hi_raw["min_session_hint_savings_bytes"], hi.min_session_hint_savings_bytes, ...boundsOf("hints.min_session_hint_savings_bytes"));
2075
2040
  hi.pre_skill_advisory = validatedBool(hi_raw["pre_skill_advisory"], hi.pre_skill_advisory);
2041
+ hi.stop_verification_advisory = validatedBool(hi_raw["stop_verification_advisory"], hi.stop_verification_advisory);
2042
+ hi.agent_receipt = validatedBool(hi_raw["agent_receipt"], hi.agent_receipt);
2076
2043
  hi.context_threshold_advisory = validatedBool(hi_raw["context_threshold_advisory"], hi.context_threshold_advisory);
2077
2044
  hi.diff_hint_min_tokens_saved = validatedInt(hi_raw["diff_hint_min_tokens_saved"], hi.diff_hint_min_tokens_saved, ...boundsOf("hints.diff_hint_min_tokens_saved"));
2078
2045
  hi.large_read_redirect_bytes = validatedIntWithLegacySentinel(hi_raw["large_read_redirect_bytes"], hi.large_read_redirect_bytes, 45e3, ...boundsOf("hints.large_read_redirect_bytes"));
2046
+ hi.first_read_symbol_bytes = validatedInt(hi_raw["first_read_symbol_bytes"], hi.first_read_symbol_bytes, ...boundsOf("hints.first_read_symbol_bytes"));
2047
+ hi.first_read_symbol_policy = validatedEnum("hints.first_read_symbol_policy", hi_raw["first_read_symbol_policy"], hi.first_read_symbol_policy);
2048
+ hi.write_blind_drop = validatedEnum("hints.write_blind_drop", hi_raw["write_blind_drop"], hi.write_blind_drop);
2049
+ hi.write_sibling_copy = validatedBool(hi_raw["write_sibling_copy"], hi.write_sibling_copy);
2050
+ hi.write_sibling_copy_allow = validatedStrList(hi_raw["write_sibling_copy_allow"], hi.write_sibling_copy_allow);
2079
2051
  hi.reread_deny = validatedBool(hi_raw["reread_deny"], hi.reread_deny);
2080
2052
  hi.reread_deny_min_bytes = validatedIntWithLegacySentinel(hi_raw["reread_deny_min_bytes"], hi.reread_deny_min_bytes, 2048, ...boundsOf("hints.reread_deny_min_bytes"));
2081
2053
  hi.stable_doc_compacts = validatedBool(hi_raw["stable_doc_compacts"], hi.stable_doc_compacts);
@@ -2087,11 +2059,14 @@ function _buildConfig(raw, projectRaw = {}) {
2087
2059
  hi.truncated_read_min_lines = validatedInt(hi_raw["truncated_read_min_lines"], hi.truncated_read_min_lines, ...boundsOf("hints.truncated_read_min_lines"));
2088
2060
  hi.protect_recent_reads = validatedInt(hi_raw["protect_recent_reads"], hi.protect_recent_reads, ...boundsOf("hints.protect_recent_reads"));
2089
2061
  hi.warn_unbalanced_shell_quoting = validatedBool(hi_raw["warn_unbalanced_shell_quoting"], hi.warn_unbalanced_shell_quoting);
2062
+ hi.deny_bash_double_backslash = validatedBool(hi_raw["deny_bash_double_backslash"], hi.deny_bash_double_backslash);
2090
2063
  hi.log_large_file_hint_outcomes = validatedBool(hi_raw["log_large_file_hint_outcomes"], hi.log_large_file_hint_outcomes);
2091
2064
  hi.warn_unbalanced_shell_quoting = envBool("TOKEN_GOAT_WARN_UNBALANCED_SHELL_QUOTING", hi.warn_unbalanced_shell_quoting);
2065
+ hi.deny_bash_double_backslash = envBool("TOKEN_GOAT_DENY_BASH_DOUBLE_BACKSLASH", hi.deny_bash_double_backslash);
2092
2066
  hi.serve_diff_on_reread = envBool("TOKEN_GOAT_SERVE_DIFF_ON_REREAD", hi.serve_diff_on_reread);
2093
2067
  hi.elide_served_lines = envBool("TOKEN_GOAT_ELIDE_SERVED_LINES", hi.elide_served_lines);
2094
2068
  hi.subagent_markdown_first_read_deny = envBool("TOKEN_GOAT_SUBAGENT_MARKDOWN_FIRST_READ_DENY", hi.subagent_markdown_first_read_deny);
2069
+ hi.agent_scoped_spawn_deny = envBool("TOKEN_GOAT_AGENT_SCOPED_SPAWN_DENY", hi.agent_scoped_spawn_deny);
2095
2070
  hi.log_large_file_hint_outcomes = envBool("TOKEN_GOAT_LOG_LARGE_FILE_HINT_OUTCOMES", hi.log_large_file_hint_outcomes);
2096
2071
  hi.json_sidecar = envBool("TOKEN_GOAT_HINT_JSON_SIDECAR", hi.json_sidecar);
2097
2072
  hi.large_read_redirect_bytes = envInt("TOKEN_GOAT_LARGE_READ_BYTES", hi.large_read_redirect_bytes, ...boundsOf("hints.large_read_redirect_bytes"));
@@ -2106,6 +2081,10 @@ function _buildConfig(raw, projectRaw = {}) {
2106
2081
  hi.min_session_hint_savings_bytes = envInt("TOKEN_GOAT_SESSION_HINT_MIN_BYTES", hi.min_session_hint_savings_bytes, ...boundsOf("hints.min_session_hint_savings_bytes"));
2107
2082
  hi.reread_deny = envBool("TOKEN_GOAT_REREAD_DENY", hi.reread_deny);
2108
2083
  hi.reread_deny_min_bytes = envInt("TOKEN_GOAT_REREAD_DENY_MIN_BYTES", hi.reread_deny_min_bytes, ...boundsOf("hints.reread_deny_min_bytes"));
2084
+ hi.first_read_symbol_bytes = envInt("TOKEN_GOAT_FIRST_READ_SYMBOL_BYTES", hi.first_read_symbol_bytes, ...boundsOf("hints.first_read_symbol_bytes"));
2085
+ hi.first_read_symbol_policy = envEnum("hints.first_read_symbol_policy", "TOKEN_GOAT_FIRST_READ_SYMBOL_POLICY", hi.first_read_symbol_policy);
2086
+ hi.write_blind_drop = envEnum("hints.write_blind_drop", "TOKEN_GOAT_WRITE_BLIND_DROP", hi.write_blind_drop);
2087
+ hi.write_sibling_copy = envBool("TOKEN_GOAT_WRITE_SIBLING_COPY", hi.write_sibling_copy);
2109
2088
  hi.protect_recent_reads = envInt("TOKEN_GOAT_PROTECT_RECENT_READS", hi.protect_recent_reads, ...boundsOf("hints.protect_recent_reads"));
2110
2089
  hi.truncated_read_min_lines = envInt("TOKEN_GOAT_TRUNCATED_READ_MIN_LINES", hi.truncated_read_min_lines, ...boundsOf("hints.truncated_read_min_lines"));
2111
2090
  hi.diff_hint_min_tokens_saved = envInt("TOKEN_GOAT_DIFF_HINT_MIN_TOKENS_SAVED", hi.diff_hint_min_tokens_saved, ...boundsOf("hints.diff_hint_min_tokens_saved"));
@@ -2119,6 +2098,8 @@ function _buildConfig(raw, projectRaw = {}) {
2119
2098
  hi.skeleton_large_sources = envBool("TOKEN_GOAT_SKELETON_LARGE_SOURCES", hi.skeleton_large_sources);
2120
2099
  hi.context_threshold_advisory = envBool("TOKEN_GOAT_CONTEXT_THRESHOLD_ADVISORY", hi.context_threshold_advisory);
2121
2100
  hi.pre_skill_advisory = envBool("TOKEN_GOAT_PRE_SKILL_ADVISORY", hi.pre_skill_advisory);
2101
+ hi.stop_verification_advisory = envBool("TOKEN_GOAT_STOP_VERIFICATION_ADVISORY", hi.stop_verification_advisory);
2102
+ hi.agent_receipt = envBool("TOKEN_GOAT_AGENT_RECEIPT", hi.agent_receipt);
2122
2103
  hi.quiet_hours = envStr("TOKEN_GOAT_QUIET_HOURS", hi.quiet_hours);
2123
2104
  const triggers_raw = hi_raw["prompt_triggers"];
2124
2105
  if (Array.isArray(triggers_raw)) {
@@ -2133,6 +2114,8 @@ function _buildConfig(raw, projectRaw = {}) {
2133
2114
  hk.latency_budget_ms = envInt("TOKEN_GOAT_HOOK_LATENCY_BUDGET_MS", hk.latency_budget_ms, ...boundsOf("hooks.latency_budget_ms"));
2134
2115
  hk.server = validatedBool(hk_raw["server"], hk.server);
2135
2116
  hk.server = envBool("TOKEN_GOAT_HOOK_SERVER", hk.server);
2117
+ hk.native = validatedNativeHooksMode(hk_raw["native"], hk.native);
2118
+ hk.native = nativeHooksModeFromEnv(process.env["TOKEN_GOAT_NATIVE_HOOKS"]) ?? hk.native;
2136
2119
  const wf_raw = section(raw, "webfetch");
2137
2120
  const wf = getDefaultConfig("webfetch");
2138
2121
  wf.allow = validatedStrList(wf_raw["allow"], wf.allow);
@@ -2163,6 +2146,7 @@ function _buildConfig(raw, projectRaw = {}) {
2163
2146
  ix.max_chunks_per_file = validatedInt(ix_raw["max_chunks_per_file"], ix.max_chunks_per_file, ...boundsOf("indexing.max_chunks_per_file"));
2164
2147
  ix.skip_dirs = validatedStrList(ix_raw["skip_dirs"], ix.skip_dirs);
2165
2148
  ix.skip_files = validatedStrList(ix_raw["skip_files"], ix.skip_files);
2149
+ ix.skip_minified = validatedBool(ix_raw["skip_minified"], ix.skip_minified);
2166
2150
  ix.embeddings_enabled = validatedBool(ix_raw["embeddings_enabled"], ix.embeddings_enabled);
2167
2151
  ix.embeddings_enabled = envBool("TOKEN_GOAT_EMBEDDINGS_ENABLED", ix.embeddings_enabled);
2168
2152
  ix.cross_project_symbols = validatedBool(ix_raw["cross_project_symbols"], ix.cross_project_symbols);
@@ -2214,6 +2198,7 @@ function _buildConfig(raw, projectRaw = {}) {
2214
2198
  sem.archive_weight = validatedFloat(sem_raw["archive_weight"], sem.archive_weight, ...boundsOf("semantic.archive_weight"));
2215
2199
  sem.docs_weight = validatedFloat(sem_raw["docs_weight"], sem.docs_weight, ...boundsOf("semantic.docs_weight"));
2216
2200
  sem.max_distance = validatedFloat(sem_raw["max_distance"], sem.max_distance, ...boundsOf("semantic.max_distance"));
2201
+ sem.weak_distance = validatedFloat(sem_raw["weak_distance"], sem.weak_distance, ...boundsOf("semantic.weak_distance"));
2217
2202
  return {
2218
2203
  compact_assist: ca,
2219
2204
  bash_compress: bc,
@@ -2227,7 +2212,6 @@ function _buildConfig(raw, projectRaw = {}) {
2227
2212
  screenshot: sc_cfg,
2228
2213
  repomap: rm,
2229
2214
  overflow_guard: og,
2230
- stats: st,
2231
2215
  hints: hi,
2232
2216
  hooks: hk,
2233
2217
  webfetch: wf,
@@ -2261,7 +2245,6 @@ var CONFIG_KEY_ENV_OVERRIDES = {
2261
2245
  "skill_preservation.pre_skill_enabled": ["TOKEN_GOAT_PRE_SKILL"],
2262
2246
  "skill_preservation.orphan_sweep_enabled": ["TOKEN_GOAT_ORPHAN_SWEEP"],
2263
2247
  "image_shrink.max_image_pixels": ["TOKEN_GOAT_MAX_IMAGE_PIXELS"],
2264
- "image_shrink.ocr_enabled": ["TOKEN_GOAT_OCR_ENABLED"],
2265
2248
  "image_shrink.ocr_lang": ["TOKEN_GOAT_OCR_LANG"],
2266
2249
  "image_shrink.vision_tier": ["TOKEN_GOAT_VISION_TIER"],
2267
2250
  "screenshot.block_private_targets": ["TOKEN_GOAT_SCREENSHOT_BLOCK_PRIVATE_TARGETS"],
@@ -2277,10 +2260,16 @@ var CONFIG_KEY_ENV_OVERRIDES = {
2277
2260
  "hints.write_rewrite_min_lines": ["TOKEN_GOAT_WRITE_REWRITE_MIN_LINES"],
2278
2261
  "hints.write_rewrite_unchanged_pct": ["TOKEN_GOAT_WRITE_REWRITE_UNCHANGED_PCT"],
2279
2262
  "hints.large_read_redirect_bytes": ["TOKEN_GOAT_LARGE_READ_BYTES"],
2263
+ "hints.first_read_symbol_bytes": ["TOKEN_GOAT_FIRST_READ_SYMBOL_BYTES"],
2264
+ "hints.first_read_symbol_policy": ["TOKEN_GOAT_FIRST_READ_SYMBOL_POLICY"],
2265
+ "hints.write_blind_drop": ["TOKEN_GOAT_WRITE_BLIND_DROP"],
2266
+ "hints.write_sibling_copy": ["TOKEN_GOAT_WRITE_SIBLING_COPY"],
2280
2267
  "hints.warn_unbalanced_shell_quoting": ["TOKEN_GOAT_WARN_UNBALANCED_SHELL_QUOTING"],
2268
+ "hints.deny_bash_double_backslash": ["TOKEN_GOAT_DENY_BASH_DOUBLE_BACKSLASH"],
2281
2269
  "hints.serve_diff_on_reread": ["TOKEN_GOAT_SERVE_DIFF_ON_REREAD"],
2282
2270
  "hints.elide_served_lines": ["TOKEN_GOAT_ELIDE_SERVED_LINES"],
2283
2271
  "hints.subagent_markdown_first_read_deny": ["TOKEN_GOAT_SUBAGENT_MARKDOWN_FIRST_READ_DENY"],
2272
+ "hints.agent_scoped_spawn_deny": ["TOKEN_GOAT_AGENT_SCOPED_SPAWN_DENY"],
2284
2273
  "hints.log_large_file_hint_outcomes": ["TOKEN_GOAT_LOG_LARGE_FILE_HINT_OUTCOMES"],
2285
2274
  "hints.cross_session_read_dedup": ["TOKEN_GOAT_CROSS_SESSION_READ_DEDUP"],
2286
2275
  "hints.cross_session_read_dedup_ttl_secs": ["TOKEN_GOAT_CROSS_SESSION_READ_DEDUP_TTL_SECS"],
@@ -2302,9 +2291,12 @@ var CONFIG_KEY_ENV_OVERRIDES = {
2302
2291
  "hints.skeleton_large_sources": ["TOKEN_GOAT_SKELETON_LARGE_SOURCES"],
2303
2292
  "hints.context_threshold_advisory": ["TOKEN_GOAT_CONTEXT_THRESHOLD_ADVISORY"],
2304
2293
  "hints.pre_skill_advisory": ["TOKEN_GOAT_PRE_SKILL_ADVISORY"],
2294
+ "hints.stop_verification_advisory": ["TOKEN_GOAT_STOP_VERIFICATION_ADVISORY"],
2295
+ "hints.agent_receipt": ["TOKEN_GOAT_AGENT_RECEIPT"],
2305
2296
  "hints.quiet_hours": ["TOKEN_GOAT_QUIET_HOURS"],
2306
2297
  "hooks.latency_budget_ms": ["TOKEN_GOAT_HOOK_LATENCY_BUDGET_MS"],
2307
2298
  "hooks.server": ["TOKEN_GOAT_HOOK_SERVER"],
2299
+ "hooks.native": ["TOKEN_GOAT_NATIVE_HOOKS"],
2308
2300
  "webfetch.max_file_count": ["TOKEN_GOAT_WEB_CACHE_MAX_FILES"],
2309
2301
  "webfetch.max_bytes": ["TOKEN_GOAT_WEB_CACHE_MAX_BYTES"],
2310
2302
  "webfetch.compress_bodies": ["TOKEN_GOAT_WEB_COMPRESS"],
@@ -2328,7 +2320,26 @@ var CONFIG_KEY_ENV_OVERRIDES = {
2328
2320
  "indexing.max_db_size_mb": ["TOKEN_GOAT_INDEXING_MAX_DB_SIZE_MB"],
2329
2321
  "indexing.auto_reclaim_embeddings": ["TOKEN_GOAT_INDEXING_AUTO_RECLAIM_EMBEDDINGS"]
2330
2322
  };
2331
- function saveConfig(config) {
2323
+ function isPlainObject(v) {
2324
+ return v !== null && typeof v === "object" && !Array.isArray(v);
2325
+ }
2326
+ function sparsifyAgainstDefaults(data, defaults, raw, explicit, prefix = "") {
2327
+ const out = {};
2328
+ for (const [k, v] of Object.entries(data)) {
2329
+ const dotted = prefix === "" ? k : `${prefix}.${k}`;
2330
+ const d = defaults[k];
2331
+ const r = raw[k];
2332
+ if (isPlainObject(v) && isPlainObject(d)) {
2333
+ const sub = sparsifyAgainstDefaults(v, d, isPlainObject(r) ? r : {}, explicit, dotted);
2334
+ if (Object.keys(sub).length > 0) out[k] = sub;
2335
+ continue;
2336
+ }
2337
+ const keep = d === void 0 || !rawValueEquals(v, d) || r !== void 0 || explicit.has(dotted);
2338
+ if (keep) out[k] = v;
2339
+ }
2340
+ return out;
2341
+ }
2342
+ function saveConfig(config, explicitKeys = []) {
2332
2343
  const ca = config.compact_assist;
2333
2344
  const bc = config.bash_compress;
2334
2345
  const sp = config.skill_preservation;
@@ -2393,7 +2404,6 @@ function saveConfig(config) {
2393
2404
  jpeg_quality: is_cfg.jpeg_quality,
2394
2405
  max_image_pixels: is_cfg.max_image_pixels,
2395
2406
  screenshot_redirect: is_cfg.screenshot_redirect,
2396
- ocr_enabled: is_cfg.ocr_enabled,
2397
2407
  ocr_min_confidence: is_cfg.ocr_min_confidence,
2398
2408
  ocr_lang: is_cfg.ocr_lang,
2399
2409
  vision_tier: is_cfg.vision_tier
@@ -2410,9 +2420,6 @@ function saveConfig(config) {
2410
2420
  enabled: config.overflow_guard.enabled,
2411
2421
  max_tokens: config.overflow_guard.max_tokens
2412
2422
  },
2413
- stats: {
2414
- record_zero_savings: config.stats.record_zero_savings
2415
- },
2416
2423
  hints: {
2417
2424
  quiet_hours: config.hints.quiet_hours,
2418
2425
  json_sidecar: config.hints.json_sidecar,
@@ -2426,13 +2433,21 @@ function saveConfig(config) {
2426
2433
  serve_diff_on_reread: config.hints.serve_diff_on_reread,
2427
2434
  elide_served_lines: config.hints.elide_served_lines,
2428
2435
  subagent_markdown_first_read_deny: config.hints.subagent_markdown_first_read_deny,
2436
+ agent_scoped_spawn_deny: config.hints.agent_scoped_spawn_deny,
2429
2437
  backoff_thresholds: config.hints.backoff_thresholds,
2430
2438
  git_hint_max_ms: config.hints.git_hint_max_ms,
2431
2439
  min_session_hint_savings_bytes: config.hints.min_session_hint_savings_bytes,
2432
2440
  pre_skill_advisory: config.hints.pre_skill_advisory,
2441
+ stop_verification_advisory: config.hints.stop_verification_advisory,
2442
+ agent_receipt: config.hints.agent_receipt,
2433
2443
  context_threshold_advisory: config.hints.context_threshold_advisory,
2434
2444
  diff_hint_min_tokens_saved: config.hints.diff_hint_min_tokens_saved,
2435
2445
  large_read_redirect_bytes: config.hints.large_read_redirect_bytes,
2446
+ first_read_symbol_bytes: config.hints.first_read_symbol_bytes,
2447
+ first_read_symbol_policy: config.hints.first_read_symbol_policy,
2448
+ write_blind_drop: config.hints.write_blind_drop,
2449
+ write_sibling_copy: config.hints.write_sibling_copy,
2450
+ write_sibling_copy_allow: config.hints.write_sibling_copy_allow,
2436
2451
  reread_deny: config.hints.reread_deny,
2437
2452
  reread_deny_min_bytes: config.hints.reread_deny_min_bytes,
2438
2453
  stable_doc_compacts: config.hints.stable_doc_compacts,
@@ -2445,6 +2460,7 @@ function saveConfig(config) {
2445
2460
  protect_recent_reads: config.hints.protect_recent_reads,
2446
2461
  prompt_triggers: config.hints.prompt_triggers,
2447
2462
  warn_unbalanced_shell_quoting: config.hints.warn_unbalanced_shell_quoting,
2463
+ deny_bash_double_backslash: config.hints.deny_bash_double_backslash,
2448
2464
  log_large_file_hint_outcomes: config.hints.log_large_file_hint_outcomes,
2449
2465
  cross_session_read_dedup: config.hints.cross_session_read_dedup,
2450
2466
  cross_session_read_dedup_ttl_secs: config.hints.cross_session_read_dedup_ttl_secs,
@@ -2453,7 +2469,8 @@ function saveConfig(config) {
2453
2469
  },
2454
2470
  hooks: {
2455
2471
  latency_budget_ms: config.hooks.latency_budget_ms,
2456
- server: config.hooks.server
2472
+ server: config.hooks.server,
2473
+ native: config.hooks.native
2457
2474
  },
2458
2475
  webfetch: {
2459
2476
  allow: config.webfetch.allow,
@@ -2475,6 +2492,7 @@ function saveConfig(config) {
2475
2492
  max_chunks_per_file: config.indexing.max_chunks_per_file,
2476
2493
  skip_dirs: config.indexing.skip_dirs,
2477
2494
  skip_files: config.indexing.skip_files,
2495
+ skip_minified: config.indexing.skip_minified,
2478
2496
  embeddings_enabled: config.indexing.embeddings_enabled,
2479
2497
  cross_project_symbols: config.indexing.cross_project_symbols,
2480
2498
  max_db_size_mb: config.indexing.max_db_size_mb,
@@ -2510,40 +2528,32 @@ function saveConfig(config) {
2510
2528
  semantic: {
2511
2529
  archive_weight: config.semantic.archive_weight,
2512
2530
  max_distance: config.semantic.max_distance,
2531
+ weak_distance: config.semantic.weak_distance,
2513
2532
  docs_weight: config.semantic.docs_weight
2514
2533
  }
2515
2534
  };
2516
- const toml = stringify(data);
2535
+ const toml = stringify(sparsifyAgainstDefaults(data, buildPersistedConfig({}), readConfigToml(configPath()).raw, new Set(explicitKeys)));
2517
2536
  atomicWriteText(configPath(), toml);
2518
- _cached2 = null;
2537
+ _cached = null;
2519
2538
  }
2520
2539
 
2521
2540
  export {
2522
2541
  parse,
2523
2542
  stringify,
2524
- setRelaySeededSessionId,
2525
- relaySeededSessionId,
2526
- detectHarness,
2527
- getHarnessName,
2528
- fingerprintContent,
2529
- shortFingerprint,
2530
- fingerprintFile,
2531
- fileIsAbsent,
2532
2543
  DEFAULT_OCR_LANG,
2533
2544
  SUPPORTED_OCR_LANG_CODES,
2534
2545
  isSupportedOcrLang,
2535
2546
  resolveOcrLangs,
2536
2547
  ownGet,
2548
+ RETIRED_CONFIG_KEYS,
2537
2549
  defaultConfig,
2538
- makeProjectAt,
2539
- findProject,
2540
- getDisplayRoot,
2541
- isUnderSystemTemp,
2542
- resolveProjectRoot,
2543
2550
  PROJECT_LOCKED_SECTIONS,
2544
2551
  PROJECT_LOCKED_KEYS,
2545
2552
  lastProjectConfigLockedKeys,
2546
2553
  readConfigSource,
2554
+ readConfigToml,
2555
+ withConfigProjectRoot,
2556
+ configProjectRootFor,
2547
2557
  getProjectConfigInfo,
2548
2558
  isAutoTriggerMultiplierExplicit,
2549
2559
  validateNumericField,
@@ -2551,20 +2561,23 @@ export {
2551
2561
  getLastConfigParseError,
2552
2562
  getLastProjectConfigParseError,
2553
2563
  resolveConfigKeyLayer,
2564
+ globalValueRejection,
2554
2565
  loadConfig,
2555
2566
  invalidateConfigCache,
2567
+ buildPersistedConfig,
2556
2568
  loadPersistedConfig,
2557
2569
  hookServerEnabled,
2570
+ nativeHooksEnabled,
2558
2571
  CONFIG_KEY_ENV_OVERRIDES,
2559
2572
  saveConfig
2560
2573
  };
2561
2574
  /*! Bundled license information:
2562
2575
 
2563
- smol-toml/dist/date.js:
2564
2576
  smol-toml/dist/error.js:
2565
- smol-toml/dist/util.js:
2566
2577
  smol-toml/dist/primitive.js:
2578
+ smol-toml/dist/date.js:
2567
2579
  smol-toml/dist/extract.js:
2580
+ smol-toml/dist/util.js:
2568
2581
  smol-toml/dist/struct.js:
2569
2582
  smol-toml/dist/parse.js:
2570
2583
  smol-toml/dist/stringify.js: