token-goat 2.9.29 → 2.9.30

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 (131) hide show
  1. package/README.md +34 -40
  2. package/SECURITY.md +28 -10
  3. package/THIRD_PARTY_NOTICES.md +40 -3
  4. package/dist/native/linux-arm64/tg-hook +0 -0
  5. package/dist/native/linux-x64/tg-hook +0 -0
  6. package/dist/ort-wasm-simd-threaded.mjs +59 -0
  7. package/dist/token-goat-chunk-3CHUNJ2O.mjs +53 -0
  8. package/dist/token-goat-chunk-3Z5S4KGM.mjs +918 -0
  9. package/dist/token-goat-chunk-4FVIAHSI.mjs +211 -0
  10. package/dist/{token-goat-chunk-PGTH2U4C.mjs → token-goat-chunk-4JJS54TR.mjs} +4 -3
  11. package/dist/token-goat-chunk-4LCCNRTG.mjs +313 -0
  12. package/dist/{token-goat-chunk-L7H3U27L.mjs → token-goat-chunk-54K3EUV3.mjs} +1 -1
  13. package/dist/token-goat-chunk-56EIMS3E.mjs +159 -0
  14. package/dist/token-goat-chunk-5BCIJXMO.mjs +609 -0
  15. package/dist/token-goat-chunk-5KDMCMF2.mjs +362 -0
  16. package/dist/token-goat-chunk-5RG5SBL6.mjs +221 -0
  17. package/dist/{token-goat-chunk-RRNZMM3A.mjs → token-goat-chunk-5Y6ZYL6U.mjs} +21 -2
  18. package/dist/{token-goat-chunk-GLXRTTLE.mjs → token-goat-chunk-64FBPDTK.mjs} +12 -8
  19. package/dist/{token-goat-chunk-G23DWHV4.mjs → token-goat-chunk-664RTTUV.mjs} +28 -15
  20. package/dist/token-goat-chunk-67TQJ76B.mjs +57 -0
  21. package/dist/token-goat-chunk-6QMAS7AB.mjs +42 -0
  22. package/dist/token-goat-chunk-7BXSNBY5.mjs +253 -0
  23. package/dist/{token-goat-chunk-IVWI2OCK.mjs → token-goat-chunk-7F2UBPD3.mjs} +40 -11
  24. package/dist/{token-goat-chunk-TGOXNAHW.mjs → token-goat-chunk-7IN2MKDS.mjs} +682 -501
  25. package/dist/token-goat-chunk-7NADEDKJ.mjs +124 -0
  26. package/dist/{token-goat-chunk-KOPIR3KZ.mjs → token-goat-chunk-A3CK6N5Z.mjs} +618 -72
  27. package/dist/{token-goat-chunk-O6I2XU4P.mjs → token-goat-chunk-AFLYLHDH.mjs} +44 -31
  28. package/dist/{token-goat-chunk-TCQANXYC.mjs → token-goat-chunk-AM5V6GSX.mjs} +18 -2
  29. package/dist/{token-goat-chunk-E4ZOJIZK.mjs → token-goat-chunk-APGZXSPS.mjs} +39 -146
  30. package/dist/{token-goat-chunk-D4ETHJD6.mjs → token-goat-chunk-ARDNEC2U.mjs} +9 -7
  31. package/dist/token-goat-chunk-ATCPY7EQ.mjs +134 -0
  32. package/dist/token-goat-chunk-B2RZZCSS.mjs +354 -0
  33. package/dist/{token-goat-chunk-BGYOZ6DO.mjs → token-goat-chunk-B45VMIIH.mjs} +6 -7
  34. package/dist/token-goat-chunk-BPGCUMR7.mjs +30 -0
  35. package/dist/{token-goat-chunk-TDUT2CL6.mjs → token-goat-chunk-C63JQV5K.mjs} +45 -6
  36. package/dist/{token-goat-chunk-ZER6EAXZ.mjs → token-goat-chunk-COBQGL5S.mjs} +2661 -2440
  37. package/dist/token-goat-chunk-COTXZHTS.mjs +39 -0
  38. package/dist/{token-goat-chunk-RQGGMPCR.mjs → token-goat-chunk-CYCEYAEO.mjs} +76 -16
  39. package/dist/token-goat-chunk-CZ3LUXYZ.mjs +4115 -0
  40. package/dist/{token-goat-chunk-ASLWOQ3I.mjs → token-goat-chunk-DZX2YDPT.mjs} +2 -1
  41. package/dist/token-goat-chunk-E3OQX2XT.mjs +824 -0
  42. package/dist/token-goat-chunk-EFHMMIGP.mjs +68 -0
  43. package/dist/token-goat-chunk-ETBHVDB6.mjs +328 -0
  44. package/dist/token-goat-chunk-EVMZJ27Z.mjs +147 -0
  45. package/dist/token-goat-chunk-EXKGNHEG.mjs +2096 -0
  46. package/dist/{token-goat-chunk-RTMVLHWX.mjs → token-goat-chunk-FBNQNSJK.mjs} +2555 -5127
  47. package/dist/{token-goat-chunk-NMTKNYGF.mjs → token-goat-chunk-FNFBKLRD.mjs} +74 -9
  48. package/dist/{token-goat-chunk-RLP6J7WR.mjs → token-goat-chunk-FZ3NEW5O.mjs} +33 -19
  49. package/dist/token-goat-chunk-G5PJ7AGM.mjs +36 -0
  50. package/dist/{token-goat-chunk-DNRPXHYH.mjs → token-goat-chunk-GFBSN7BD.mjs} +29 -401
  51. package/dist/{token-goat-chunk-XYWPOSCN.mjs → token-goat-chunk-GOLEOXZP.mjs} +763 -211
  52. package/dist/token-goat-chunk-H2K3QP6H.mjs +24 -0
  53. package/dist/token-goat-chunk-H2PHHGM5.mjs +188 -0
  54. package/dist/token-goat-chunk-HAVAOB3S.mjs +87 -0
  55. package/dist/token-goat-chunk-HG45AF2B.mjs +2228 -0
  56. package/dist/{token-goat-chunk-HUYUHODZ.mjs → token-goat-chunk-HOJLCGDP.mjs} +12965 -11748
  57. package/dist/{token-goat-chunk-435UQTKD.mjs → token-goat-chunk-HYBFA5X3.mjs} +118 -19
  58. package/dist/token-goat-chunk-IVALLT3S.mjs +48 -0
  59. package/dist/{token-goat-chunk-UXSXQQIY.mjs → token-goat-chunk-IVKIZWAB.mjs} +3 -3
  60. package/dist/{token-goat-chunk-52NSDWYY.mjs → token-goat-chunk-JB6QN6VF.mjs} +6 -4
  61. package/dist/{token-goat-chunk-HNFZZHFW.mjs → token-goat-chunk-JDHE26RP.mjs} +10 -3
  62. package/dist/{token-goat-chunk-FTP4U4QA.mjs → token-goat-chunk-JDU3EXSU.mjs} +12 -11
  63. package/dist/token-goat-chunk-JDWCRD6M.mjs +253 -0
  64. package/dist/{token-goat-chunk-6AK46ZT7.mjs → token-goat-chunk-JN4XMLSD.mjs} +5 -1
  65. package/dist/token-goat-chunk-JTQQGXZH.mjs +733 -0
  66. package/dist/token-goat-chunk-KKUFXAPD.mjs +25 -0
  67. package/dist/token-goat-chunk-KQNZDCBD.mjs +47 -0
  68. package/dist/{token-goat-chunk-2WOUYWLM.mjs → token-goat-chunk-KWPNJBDH.mjs} +27 -3
  69. package/dist/{token-goat-chunk-DPNLUJWB.mjs → token-goat-chunk-LOBGHXPB.mjs} +30 -8
  70. package/dist/token-goat-chunk-MKPF4CL5.mjs +37 -0
  71. package/dist/token-goat-chunk-MNWKPRAL.mjs +13 -0
  72. package/dist/{token-goat-chunk-DNSPXQXQ.mjs → token-goat-chunk-N2NMER56.mjs} +25 -15
  73. package/dist/token-goat-chunk-NYKZLXMK.mjs +218 -0
  74. package/dist/token-goat-chunk-OJBNYTJP.mjs +3087 -0
  75. package/dist/token-goat-chunk-P4QMM4WK.mjs +295 -0
  76. package/dist/token-goat-chunk-PD5VKH46.mjs +184 -0
  77. package/dist/token-goat-chunk-PEPTHRFF.mjs +129 -0
  78. package/dist/{token-goat-chunk-NMBWLRHW.mjs → token-goat-chunk-PU7V3FD6.mjs} +8721 -11104
  79. package/dist/token-goat-chunk-PY533T7F.mjs +46 -0
  80. package/dist/token-goat-chunk-Q5VTGRH7.mjs +761 -0
  81. package/dist/{token-goat-chunk-67BNIKKO.mjs → token-goat-chunk-QCLDAQTS.mjs} +31 -20
  82. package/dist/{token-goat-chunk-SE6E4BKJ.mjs → token-goat-chunk-QSBRTGM2.mjs} +9 -2
  83. package/dist/{token-goat-chunk-VZQEWRVH.mjs → token-goat-chunk-RC35RBUL.mjs} +4 -4
  84. package/dist/{token-goat-chunk-VMFWNHGR.mjs → token-goat-chunk-RHXKCZX3.mjs} +873 -504
  85. package/dist/{token-goat-chunk-PYSUADX4.mjs → token-goat-chunk-RZRTDST7.mjs} +17 -7
  86. package/dist/{token-goat-chunk-ONXH6NZ5.mjs → token-goat-chunk-SJHWVNDQ.mjs} +15 -21
  87. package/dist/token-goat-chunk-SMVRN2HU.mjs +188 -0
  88. package/dist/{token-goat-chunk-QO3LXVVR.mjs → token-goat-chunk-SQSSNQPE.mjs} +2295 -1718
  89. package/dist/{token-goat-chunk-2AWQ2R5X.mjs → token-goat-chunk-T4FK7VOV.mjs} +2 -2
  90. package/dist/token-goat-chunk-U4N3BN2W.mjs +92 -0
  91. package/dist/token-goat-chunk-UA5V6P3P.mjs +122 -0
  92. package/dist/{token-goat-chunk-UA5BKWWQ.mjs → token-goat-chunk-UQ5UK2T7.mjs} +15 -4
  93. package/dist/token-goat-chunk-USILZ3T3.mjs +53 -0
  94. package/dist/{token-goat-chunk-MELOKFDJ.mjs → token-goat-chunk-VES7EL7O.mjs} +7 -1
  95. package/dist/{token-goat-chunk-7CPMDFGB.mjs → token-goat-chunk-VL3YIFHZ.mjs} +389 -14
  96. package/dist/{token-goat-chunk-E5TK5DNO.mjs → token-goat-chunk-VPBBTSJR.mjs} +356 -129
  97. package/dist/{token-goat-chunk-YOOVFPTP.mjs → token-goat-chunk-W3QCJS6G.mjs} +10 -2
  98. package/dist/{token-goat-chunk-LZNBQTDK.mjs → token-goat-chunk-WY3L4DVT.mjs} +11 -7
  99. package/dist/token-goat-chunk-XKI4SEMX.mjs +66 -0
  100. package/dist/token-goat-chunk-XU4P6Z24.mjs +133 -0
  101. package/dist/{token-goat-chunk-H5J3C56Q.mjs → token-goat-chunk-Y776AENC.mjs} +112 -26
  102. package/dist/token-goat-chunk-YARZFCZS.mjs +359 -0
  103. package/dist/{token-goat-chunk-S4VSXURL.mjs → token-goat-chunk-Z44YO3QZ.mjs} +4 -0
  104. package/dist/token-goat-chunk-Z57YODA2.mjs +35 -0
  105. package/dist/{token-goat-chunk-PQ53BSCF.mjs → token-goat-chunk-ZCDTCVIS.mjs} +48 -29
  106. package/dist/token-goat-chunk-ZEJVMUQH.mjs +48 -0
  107. package/dist/{token-goat-chunk-BGHSSJUA.mjs → token-goat-chunk-ZFOBKUWH.mjs} +1 -1
  108. package/dist/token-goat-chunk-ZMBL6UVV.mjs +110 -0
  109. package/dist/{token-goat-chunk-PKRWMHVP.mjs → token-goat-chunk-ZQSJMO2R.mjs} +338 -170
  110. package/dist/token-goat-hook-client.cjs +87 -23
  111. package/dist/token-goat-hook-client.mjs +3 -3
  112. package/dist/token-goat-hook.mjs +46 -30
  113. package/dist/token-goat.core.mjs +6 -6
  114. package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
  115. package/docs/cli.md +80 -46
  116. package/docs/install.md +47 -14
  117. package/docs/security.md +7 -7
  118. package/package.json +17 -7
  119. package/scripts/verify-native-dist.mjs +386 -0
  120. package/dist/token-goat-chunk-2NNUA2LR.mjs +0 -143
  121. package/dist/token-goat-chunk-44BM7DDQ.mjs +0 -294
  122. package/dist/token-goat-chunk-C5YPNZKQ.mjs +0 -318
  123. package/dist/token-goat-chunk-CIQ2FTY3.mjs +0 -1990
  124. package/dist/token-goat-chunk-EUSDXRXU.mjs +0 -1429
  125. package/dist/token-goat-chunk-G7IWXCFF.mjs +0 -456
  126. package/dist/token-goat-chunk-JTKCQMQA.mjs +0 -418
  127. package/dist/token-goat-chunk-ORNFMIER.mjs +0 -295
  128. package/dist/token-goat-chunk-VQ6F6T7X.mjs +0 -36
  129. package/dist/token-goat-chunk-YAGLESS3.mjs +0 -23
  130. package/dist/token-goat-chunk-YKSRAWUU.mjs +0 -33
  131. package/dist/token-goat-chunk-Z6KBMOBI.mjs +0 -53
@@ -6,178 +6,32 @@ import {
6
6
  quotePowershellPath,
7
7
  quoteShellPath,
8
8
  sleepSync
9
- } from "./token-goat-chunk-TCQANXYC.mjs";
9
+ } from "./token-goat-chunk-AM5V6GSX.mjs";
10
10
  import {
11
11
  normalizePath
12
- } from "./token-goat-chunk-NMTKNYGF.mjs";
12
+ } from "./token-goat-chunk-FNFBKLRD.mjs";
13
13
  import {
14
14
  dataDir,
15
15
  ensureStorageRootPrivate,
16
16
  isTokenGoatStorage
17
- } from "./token-goat-chunk-MELOKFDJ.mjs";
18
- import {
19
- compileGuardedRegex
20
- } from "./token-goat-chunk-JTKCQMQA.mjs";
17
+ } from "./token-goat-chunk-VES7EL7O.mjs";
21
18
  import {
22
19
  init_define_import_meta_env
23
20
  } from "./token-goat-chunk-A37V4PBF.mjs";
24
21
 
25
- // src/encoding.ts
22
+ // src/bridges/created_configs.ts
26
23
  init_define_import_meta_env();
27
- function stripBom(text) {
28
- return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
29
- }
30
- function detectSourceEncoding(buf) {
31
- if (buf.length >= 4) {
32
- if (buf[0] === 255 && buf[1] === 254 && buf[2] === 0 && buf[3] === 0) return "utf32le";
33
- if (buf[0] === 0 && buf[1] === 0 && buf[2] === 254 && buf[3] === 255) return "utf32be";
34
- }
35
- if (buf.length >= 2) {
36
- if (buf[0] === 255 && buf[1] === 254) return "utf16le";
37
- if (buf[0] === 254 && buf[1] === 255) return "utf16be";
38
- }
39
- if (buf.length >= 3 && buf[0] === 239 && buf[1] === 187 && buf[2] === 191) return "utf8-bom";
40
- return "utf8";
41
- }
42
- function decodeSource(buf) {
43
- switch (detectSourceEncoding(buf)) {
44
- case "utf32le":
45
- return decodeUtf32(buf.subarray(4), true);
46
- case "utf32be":
47
- return decodeUtf32(buf.subarray(4), false);
48
- case "utf16le":
49
- return buf.subarray(2).toString("utf16le");
50
- case "utf16be":
51
- return swap16(buf.subarray(2)).toString("utf16le");
52
- case "utf8-bom":
53
- return buf.subarray(3).toString("utf8");
54
- default:
55
- return buf.toString("utf8");
56
- }
57
- }
58
- function encodeSource(text, encoding) {
59
- switch (encoding) {
60
- case "utf32le":
61
- return Buffer.concat([Buffer.from([255, 254, 0, 0]), encodeUtf32(text, true)]);
62
- case "utf32be":
63
- return Buffer.concat([Buffer.from([0, 0, 254, 255]), encodeUtf32(text, false)]);
64
- case "utf16le":
65
- return Buffer.concat([Buffer.from([255, 254]), Buffer.from(text, "utf16le")]);
66
- case "utf16be":
67
- return Buffer.concat([Buffer.from([254, 255]), swap16(Buffer.from(text, "utf16le"))]);
68
- case "utf8-bom":
69
- return Buffer.concat([Buffer.from([239, 187, 191]), Buffer.from(text, "utf8")]);
70
- default:
71
- return Buffer.from(text, "utf8");
72
- }
73
- }
74
- function swap16(buf) {
75
- const out = Buffer.from(buf);
76
- return out.subarray(0, out.length - out.length % 2).swap16();
77
- }
78
- function decodeUtf32(buf, littleEndian) {
79
- const points = [];
80
- for (let i = 0; i + 4 <= buf.length; i += 4) {
81
- const cp = littleEndian ? buf.readUInt32LE(i) : buf.readUInt32BE(i);
82
- points.push(cp > 1114111 || cp >= 55296 && cp <= 57343 ? 65533 : cp);
83
- }
84
- return String.fromCodePoint(...points);
85
- }
86
- function encodeUtf32(text, littleEndian) {
87
- const points = [...text];
88
- const out = Buffer.alloc(points.length * 4);
89
- points.forEach((ch, i) => {
90
- const cp = ch.codePointAt(0) ?? 65533;
91
- if (littleEndian) out.writeUInt32LE(cp, i * 4);
92
- else out.writeUInt32BE(cp, i * 4);
93
- });
94
- return out;
95
- }
24
+ import * as fs from "fs";
25
+ import * as path4 from "path";
96
26
 
97
27
  // src/util.ts
98
28
  init_define_import_meta_env();
99
- import { chmodSync, closeSync, constants as fsConstants, copyFileSync, existsSync as existsSync2, mkdirSync, openSync, readdirSync, readFileSync as readFileSync3, renameSync, rmdirSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
100
- import * as path4 from "node:path";
101
-
102
- // src/bridges/created_configs.ts
103
- init_define_import_meta_env();
104
- import * as fs from "fs";
105
- import * as path from "path";
106
- function ledgerPath() {
107
- return path.join(dataDir(), "created-configs.json");
108
- }
109
- function keyOf(filePath) {
110
- return normalizePath(path.resolve(filePath));
111
- }
112
- function foldKey(key) {
113
- return foldPath(key);
114
- }
115
- function readLedger() {
116
- try {
117
- const parsed = JSON.parse(fs.readFileSync(ledgerPath(), "utf8"));
118
- return Array.isArray(parsed) ? parsed.filter((entry) => typeof entry === "string") : [];
119
- } catch {
120
- return [];
121
- }
122
- }
123
- function writeLedger(entries) {
124
- try {
125
- ensureDirSync(path.dirname(ledgerPath()));
126
- atomicWriteText(ledgerPath(), `${JSON.stringify(entries)}
127
- `);
128
- } catch {
129
- }
130
- }
131
- function recordCreatedConfig(filePath) {
132
- const key = keyOf(filePath);
133
- const entries = readLedger();
134
- if (entries.some((entry) => foldKey(entry) === foldKey(key))) return;
135
- writeLedger([...entries, key]);
136
- }
137
- function hasCreatedConfig(filePath) {
138
- const key = foldKey(keyOf(filePath));
139
- return readLedger().some((entry) => foldKey(entry) === key);
140
- }
141
- function takeCreatedConfig(filePath) {
142
- const key = foldKey(keyOf(filePath));
143
- const entries = readLedger();
144
- if (!entries.some((entry) => foldKey(entry) === key)) return false;
145
- writeLedger(entries.filter((entry) => foldKey(entry) !== key));
146
- return true;
147
- }
148
- function recordCreatedBackup(backupPath) {
149
- recordCreatedConfig(backupPath);
150
- }
151
- function forgetCreatedBackup(backupPath) {
152
- takeCreatedConfig(backupPath);
153
- }
154
- function createdBackupsFor(configPath) {
155
- const prefix = foldKey(`${keyOf(configPath)}.bak.`);
156
- return readLedger().filter((entry) => foldKey(entry).startsWith(prefix)).sort();
157
- }
158
- function removeCreatedBackups(configPath) {
159
- const prefix = foldKey(`${keyOf(configPath)}.bak.`);
160
- const entries = readLedger();
161
- const ours = entries.filter((entry) => foldKey(entry).startsWith(prefix));
162
- if (ours.length === 0) return 0;
163
- const failed = /* @__PURE__ */ new Set();
164
- let removed = 0;
165
- for (const target of ours) {
166
- try {
167
- if (fs.existsSync(target) && removeFileInScope(target)) {
168
- removed++;
169
- }
170
- } catch {
171
- failed.add(target);
172
- }
173
- }
174
- writeLedger(entries.filter((entry) => !ours.includes(entry) || failed.has(entry)));
175
- return removed;
176
- }
29
+ import { chmodSync, closeSync, constants as fsConstants, copyFileSync, existsSync, lstatSync, mkdirSync, openSync, readdirSync, readFileSync as readFileSync2, readlinkSync, renameSync, rmdirSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
30
+ import * as path3 from "node:path";
177
31
 
178
32
  // src/bridges/project_scope_guard.ts
179
33
  init_define_import_meta_env();
180
- import * as path2 from "node:path";
34
+ import * as path from "node:path";
181
35
  function assertProjectScopeTarget(target, projectRoot) {
182
36
  if (projectRoot === void 0) return;
183
37
  if (isInsideRoot(target, projectRoot)) return;
@@ -188,7 +42,7 @@ function assertProjectScopeTarget(target, projectRoot) {
188
42
  var installProjectRoot;
189
43
  function withInstallScope(projectRoot, fn) {
190
44
  const previous = installProjectRoot;
191
- installProjectRoot = projectRoot === void 0 ? void 0 : path2.resolve(projectRoot);
45
+ installProjectRoot = projectRoot === void 0 ? void 0 : path.resolve(projectRoot);
192
46
  try {
193
47
  const result = fn();
194
48
  if (typeof result?.then === "function") {
@@ -204,7 +58,7 @@ function withInstallScope(projectRoot, fn) {
204
58
  function projectScopeRoot(opts) {
205
59
  if (opts === void 0) return void 0;
206
60
  if (opts.project !== true && opts.local !== true) return void 0;
207
- return path2.resolve(opts.projectRoot ?? process.cwd());
61
+ return path.resolve(opts.projectRoot ?? process.cwd());
208
62
  }
209
63
  function assertWriteInScope(target) {
210
64
  const root = installProjectRoot;
@@ -219,10 +73,425 @@ function projectPathIsConsultable(target, projectRoot) {
219
73
  // src/util.ts
220
74
  import { spawnSync } from "node:child_process";
221
75
 
76
+ // src/regex_guard.ts
77
+ init_define_import_meta_env();
78
+ var GROUP_PREFIX = String.raw`\((?:\?(?::|<?[=!]|<\w+>|[a-z]*(?:-[a-z]*)?:))?`;
79
+ var NESTED_QUANTIFIER = new RegExp(GROUP_PREFIX + String.raw`[^()*+]*(?:[*+]|\{\d+,\d*\})[^()]*\)\s*(?:[*+]|\{\d+,\d*\})`);
80
+ function hasNestedQuantifier(source) {
81
+ return NESTED_QUANTIFIER.test(source);
82
+ }
83
+ var PROBE_ALPHABETS = ["a", "0", "a0"];
84
+ var PROBE_STEP = 4;
85
+ var PROBE_MAX_LENGTH = 512;
86
+ var PROBE_LENGTHS = Array.from({ length: PROBE_MAX_LENGTH / PROBE_STEP }, (_, i) => (i + 1) * PROBE_STEP);
87
+ var PROJECTED_LINE_LENGTH = 1e4;
88
+ var PROJECTION_BUDGET_MS = 1e3;
89
+ var TIMING_SIGNAL_MS = 1;
90
+ var PROBE_GROWTH_FACTOR = 12;
91
+ function climbsBetweenRungs(previous, elapsed) {
92
+ return previous !== void 0 && elapsed > TIMING_SIGNAL_MS && elapsed > previous * PROBE_GROWTH_FACTOR;
93
+ }
94
+ var PROBE_TERMINATORS = ["!", "a", "0", " ", "\uFFFF", "\n", "\u2028"];
95
+ var PROBE_BUDGET_MS = 25;
96
+ var LINEAR_BY_CONSTRUCTION_EXCLUDES = /[*+?{|]/;
97
+ var MAX_COUNTED_REPEAT = 8;
98
+ var LITERAL_RUN_ATOM = /[^\\()[\]{}|^$*+?]/;
99
+ var QUANTIFIER_AT = /^[*+?{]/;
100
+ function timeMatch(re, input) {
101
+ const probe = new RegExp(re.source, re.flags.replace("g", ""));
102
+ const started = performance.now();
103
+ const matched = probe.test(input);
104
+ const first = performance.now() - started;
105
+ if (first <= TIMING_SIGNAL_MS) return { ms: first, matched };
106
+ const again = new RegExp(re.source, re.flags.replace("g", ""));
107
+ const restarted = performance.now();
108
+ again.test(input);
109
+ return { ms: Math.min(first, performance.now() - restarted), matched };
110
+ }
111
+ function confirmed(re, input, first) {
112
+ const again = timeMatch(re, input);
113
+ return again.ms < first.ms ? { ms: again.ms, matched: first.matched } : first;
114
+ }
115
+ function remeasuredForProjection(re, timings, inputs) {
116
+ const hi = timings.length - 1;
117
+ const hiLength = PROBE_LENGTHS[hi];
118
+ const lo = hiLength === void 0 ? -1 : PROBE_LENGTHS.findIndex((l) => l * 2 >= hiLength);
119
+ const out = [...timings];
120
+ for (const i of /* @__PURE__ */ new Set([lo, hi])) {
121
+ const input = inputs[i];
122
+ const ms = out[i];
123
+ if (input !== void 0 && ms !== void 0) out[i] = Math.min(ms, timeMatch(re, input).ms);
124
+ }
125
+ return out;
126
+ }
127
+ var ESCAPE_SAMPLES = {
128
+ s: " ",
129
+ S: "a",
130
+ d: "0",
131
+ D: "a",
132
+ w: "a",
133
+ W: "-",
134
+ t: " ",
135
+ n: "\n",
136
+ r: "\r",
137
+ f: "\f",
138
+ v: "\v",
139
+ "0": "\0",
140
+ b: "",
141
+ B: ""
142
+ };
143
+ var LOOKAROUND_AT = /^\(\?<?[=!]/;
144
+ var CLASS_CANDIDATES = ["a", "0", " ", "x", "-", "!", "~", " ", "\n", "A", "\xE9", "\u03B1", "\u0434", "\u05D0", "\u0627", "\u4E2D", "\u3042", "\u{1F600}"];
145
+ function firstMatch(source, flags, candidates) {
146
+ let re;
147
+ try {
148
+ re = new RegExp(source, flags);
149
+ } catch {
150
+ return "";
151
+ }
152
+ for (const candidate of candidates) if (re.test(candidate)) return candidate;
153
+ return "";
154
+ }
155
+ function classEnd(source, start) {
156
+ let i = start + 1;
157
+ if (source[i] === "^") i++;
158
+ if (source[i] === "]") i++;
159
+ for (; i < source.length; i++) {
160
+ if (source[i] === "\\") {
161
+ i++;
162
+ continue;
163
+ }
164
+ if (source[i] === "]") return i;
165
+ }
166
+ return -1;
167
+ }
168
+ var CLASS_SWEEP = [
169
+ ...Array.from({ length: 95 }, (_, i) => String.fromCharCode(32 + i)),
170
+ ...Array.from({ length: 1024 }, (_, i) => String.fromCharCode(160 + i * 63))
171
+ ];
172
+ var SWEEP_TAILS = CLASS_SWEEP.flatMap((c, i) => {
173
+ const other = CLASS_SWEEP[(i + 1) % CLASS_SWEEP.length];
174
+ return [c.repeat(MAX_COUNTED_REPEAT + 1), c.repeat(MAX_COUNTED_REPEAT) + other];
175
+ });
176
+ var MAX_SWEEPS = 3;
177
+ var SWEEP_BUDGET_MS = 150;
178
+ var QUANTIFIED_GROUP = /\)\s*(?:[*+]|\{\d+(?:,\d*)?\})/;
179
+ function sampleClass(cls) {
180
+ const named = sampleCharacters(cls.slice(1, -1));
181
+ return firstMatch(cls, "", [...named, ...CLASS_CANDIDATES]) || firstMatch(cls, "", CLASS_SWEEP);
182
+ }
183
+ function sampleCharacters(source) {
184
+ const out = [];
185
+ const seen = /* @__PURE__ */ new Set();
186
+ const push = (c) => {
187
+ if (c === "" || seen.has(c)) return;
188
+ seen.add(c);
189
+ out.push(c);
190
+ };
191
+ for (let i = 0; i < source.length; i++) {
192
+ const c = source[i];
193
+ if (c === "[") {
194
+ const end = classEnd(source, i);
195
+ if (end !== -1) {
196
+ push(sampleClass(source.slice(i, end + 1)));
197
+ i = end;
198
+ continue;
199
+ }
200
+ }
201
+ if (c !== "\\") {
202
+ if (/[^\s()[\]{}|^$*+?.-]/.test(c)) push(c);
203
+ continue;
204
+ }
205
+ const next = source[i + 1] ?? "";
206
+ i++;
207
+ if (next >= "0" && next <= "7") {
208
+ let digits = /^[0-7]{1,3}/.exec(source.slice(i))[0];
209
+ if (parseInt(digits, 8) > 255) digits = digits.slice(0, 2);
210
+ push(String.fromCharCode(parseInt(digits, 8)));
211
+ if (digits.length === 1 && next !== "0") push(next);
212
+ i += digits.length - 1;
213
+ continue;
214
+ }
215
+ if (next === "x" || next === "u") {
216
+ if (next === "u" && source[i + 1] === "{") {
217
+ const close = source.indexOf("}", i + 2);
218
+ const digits2 = close === -1 ? "" : source.slice(i + 2, close);
219
+ if (/^[0-9a-fA-F]{1,6}$/.test(digits2)) {
220
+ push(String.fromCodePoint(parseInt(digits2, 16)));
221
+ i = close;
222
+ }
223
+ continue;
224
+ }
225
+ const width = next === "x" ? 2 : 4;
226
+ const digits = source.slice(i + 1, i + 1 + width);
227
+ i += width;
228
+ if (/^[0-9a-fA-F]+$/.test(digits) && digits.length === width) push(String.fromCharCode(parseInt(digits, 16)));
229
+ continue;
230
+ }
231
+ if (next === "c" && /[a-zA-Z]/.test(source[i + 1] ?? "")) {
232
+ push(String.fromCharCode(source[i + 1].toUpperCase().charCodeAt(0) % 32));
233
+ i++;
234
+ continue;
235
+ }
236
+ if ((next === "p" || next === "P") && source[i + 1] === "{") {
237
+ const close = source.indexOf("}", i + 2);
238
+ if (close !== -1) {
239
+ push(firstMatch(source.slice(i - 1, close + 1), "u", CLASS_CANDIDATES));
240
+ i = close;
241
+ continue;
242
+ }
243
+ }
244
+ const sample = ESCAPE_SAMPLES[next];
245
+ push(sample ?? next);
246
+ }
247
+ return out;
248
+ }
249
+ var MAX_PATTERN_ALPHABETS = 12;
250
+ function probeAlphabets(source) {
251
+ const samples = sampleCharacters(source);
252
+ const counts = /* @__PURE__ */ new Map();
253
+ for (const ch of source) counts.set(ch, (counts.get(ch) ?? 0) + 1);
254
+ const counted = samples.map((c, i) => ({ c, i, n: counts.get(c) ?? 0 }));
255
+ counted.sort((a, b) => b.n - a.n || a.i - b.i);
256
+ const kept = counted.slice(0, MAX_PATTERN_ALPHABETS).map((s) => s.c);
257
+ const extra = kept.length > 1 ? [kept.join("")] : [];
258
+ return [...PROBE_ALPHABETS, ...kept, ...extra];
259
+ }
260
+ function growsExponentially(re) {
261
+ const relaxed = detune(re.source);
262
+ if (relaxed === null || !relaxed.hadLookaround) {
263
+ const cause = climbsPastBudget(re);
264
+ if (cause !== null) return cause;
265
+ }
266
+ if (relaxed === null) return null;
267
+ for (const body of relaxed.negativeBodies) {
268
+ let inner;
269
+ try {
270
+ inner = new RegExp(body, re.flags);
271
+ } catch {
272
+ continue;
273
+ }
274
+ const innerCause = growsExponentially(inner);
275
+ if (innerCause !== null) return innerCause;
276
+ }
277
+ let widened;
278
+ try {
279
+ widened = new RegExp(relaxed.source, re.flags);
280
+ } catch {
281
+ return null;
282
+ }
283
+ return growsExponentially(widened);
284
+ }
285
+ function climbsPastBudget(re) {
286
+ const probe = new RegExp(re.source, re.flags.replace("g", ""));
287
+ let sweptMs = 0;
288
+ let falsified = false;
289
+ for (const alphabet of probeAlphabets(re.source)) {
290
+ let sweeps = 0;
291
+ const body = (n) => alphabet.repeat(Math.ceil(n / alphabet.length)).slice(0, n);
292
+ const tail = PROBE_TERMINATORS.find((t) => !probe.test(body(PROBE_STEP) + t)) ?? PROBE_TERMINATORS[0];
293
+ const candidates = [tail, ...PROBE_TERMINATORS.filter((t) => t !== tail)];
294
+ let swept;
295
+ const timings = [];
296
+ const inputs = [];
297
+ let previous;
298
+ for (const length of PROBE_LENGTHS) {
299
+ let failing;
300
+ let last;
301
+ let failingInput = "";
302
+ let lastInput = "";
303
+ const attempt = (candidate) => {
304
+ const input = body(length) + candidate;
305
+ let m = timeMatch(re, input);
306
+ if (m.ms > PROBE_BUDGET_MS) m = confirmed(re, input, m);
307
+ last = m;
308
+ lastInput = input;
309
+ if (m.ms > PROBE_BUDGET_MS) return "over-budget";
310
+ if (!m.matched) {
311
+ failing = m;
312
+ failingInput = input;
313
+ }
314
+ return m;
315
+ };
316
+ for (const candidate of swept === void 0 ? candidates : [swept, ...candidates]) {
317
+ if (attempt(candidate) === "over-budget") return "over-budget";
318
+ if (failing !== void 0) break;
319
+ }
320
+ if (failing === void 0 && sweeps < MAX_SWEEPS && sweptMs < SWEEP_BUDGET_MS) {
321
+ sweeps++;
322
+ const sweepStarted = Date.now();
323
+ for (const candidate of SWEEP_TAILS) {
324
+ if (attempt(candidate) === "over-budget") return "over-budget";
325
+ if (failing !== void 0) {
326
+ swept = candidate;
327
+ break;
328
+ }
329
+ }
330
+ sweptMs += Date.now() - sweepStarted;
331
+ }
332
+ if (failing !== void 0) falsified = true;
333
+ let elapsed = (failing ?? last).ms;
334
+ const rungInput = failing !== void 0 ? failingInput : lastInput;
335
+ if (climbsBetweenRungs(previous, elapsed)) {
336
+ elapsed = confirmed(re, rungInput, { ms: elapsed, matched: false }).ms;
337
+ if (climbsBetweenRungs(previous, elapsed)) return "ratio";
338
+ }
339
+ previous = elapsed;
340
+ timings.push(elapsed);
341
+ inputs.push(rungInput);
342
+ }
343
+ if (projectsPastBudget(timings) && projectsPastBudget(remeasuredForProjection(re, timings, inputs))) return "projection";
344
+ }
345
+ if (!falsified && QUANTIFIED_GROUP.test(re.source)) return "unfalsifiable";
346
+ return null;
347
+ }
348
+ function groupEnd(source, start) {
349
+ let depth = 0;
350
+ let inClass = false;
351
+ for (let i = start; i < source.length; i++) {
352
+ const c = source[i];
353
+ if (c === "\\") {
354
+ i++;
355
+ continue;
356
+ }
357
+ if (inClass) {
358
+ if (c === "]") inClass = false;
359
+ continue;
360
+ }
361
+ if (c === "[") inClass = true;
362
+ else if (c === "(") depth++;
363
+ else if (c === ")" && --depth === 0) return i;
364
+ }
365
+ return -1;
366
+ }
367
+ function detune(source) {
368
+ let out = "";
369
+ let changed = false;
370
+ let hadLookaround = false;
371
+ const negativeBodies = [];
372
+ let inClass = false;
373
+ for (let i = 0; i < source.length; i++) {
374
+ const c = source[i];
375
+ if (c === "\\") {
376
+ out += c + (source[i + 1] ?? "");
377
+ i++;
378
+ continue;
379
+ }
380
+ if (inClass) {
381
+ out += c;
382
+ if (c === "]") inClass = false;
383
+ continue;
384
+ }
385
+ if (c === "[") {
386
+ out += c;
387
+ inClass = true;
388
+ continue;
389
+ }
390
+ if (c === "{") {
391
+ const counted = /^\{(\d+)(,(\d*))?\}/.exec(source.slice(i));
392
+ if (counted !== null) {
393
+ const min = Math.min(parseInt(counted[1], 10), MAX_COUNTED_REPEAT);
394
+ const upper = counted[3];
395
+ const max = upper === void 0 || upper === "" ? "" : String(Math.min(parseInt(upper, 10), MAX_COUNTED_REPEAT));
396
+ const rebuilt = counted[2] === void 0 ? `{${min}}` : `{${min},${max}}`;
397
+ if (rebuilt !== counted[0]) changed = true;
398
+ out += rebuilt;
399
+ i += counted[0].length - 1;
400
+ continue;
401
+ }
402
+ }
403
+ if (c === "(" && LOOKAROUND_AT.test(source.slice(i, i + 4))) {
404
+ const end = groupEnd(source, i);
405
+ if (end === -1) return null;
406
+ const behind = source[i + 2] === "<";
407
+ const negative = source[i + (behind ? 3 : 2)] === "!";
408
+ const body = source.slice(i + (behind ? 4 : 3), end);
409
+ if (negative) negativeBodies.push(body);
410
+ else out += `(?:${body})`;
411
+ i = end;
412
+ changed = true;
413
+ hadLookaround = true;
414
+ continue;
415
+ }
416
+ if (LITERAL_RUN_ATOM.test(c)) {
417
+ let run = 1;
418
+ while (source[i + run] === c) run++;
419
+ const quantified = QUANTIFIER_AT.test(source.slice(i + run, i + run + 1));
420
+ const collapsible = quantified ? run - 1 : run;
421
+ if (collapsible > MAX_COUNTED_REPEAT) {
422
+ out += c.repeat(MAX_COUNTED_REPEAT) + (quantified ? c : "");
423
+ i += run - 1;
424
+ changed = true;
425
+ continue;
426
+ }
427
+ }
428
+ out += c;
429
+ }
430
+ return changed ? { source: out, hadLookaround, negativeBodies } : null;
431
+ }
432
+ function projectsPastBudget(timings) {
433
+ const hi = timings.length - 1;
434
+ const hiLength = PROBE_LENGTHS[hi];
435
+ if (hiLength === void 0) return false;
436
+ const lo = PROBE_LENGTHS.findIndex((l) => l * 2 >= hiLength);
437
+ const loLength = PROBE_LENGTHS[lo];
438
+ const top = timings[hi];
439
+ const prior = timings[lo];
440
+ if (top === void 0 || prior === void 0 || loLength === void 0 || loLength >= hiLength) return false;
441
+ if (top <= TIMING_SIGNAL_MS || prior <= 0) return false;
442
+ const exponent = Math.log2(top / prior) / Math.log2(hiLength / loLength);
443
+ return top * (PROJECTED_LINE_LENGTH / hiLength) ** exponent > PROJECTION_BUDGET_MS;
444
+ }
445
+ var MAX_PATTERN_LENGTH = 4096;
446
+ function compileGuardedRegex(pattern, flags = "") {
447
+ if (pattern.length > MAX_PATTERN_LENGTH) {
448
+ return { ok: false, reason: `is longer than ${MAX_PATTERN_LENGTH} characters, which is past what can be checked for a stall` };
449
+ }
450
+ let re;
451
+ try {
452
+ re = new RegExp(pattern, flags);
453
+ } catch (e) {
454
+ return { ok: false, reason: e instanceof Error ? e.message : "is not a valid regular expression" };
455
+ }
456
+ if (!LINEAR_BY_CONSTRUCTION_EXCLUDES.test(pattern)) return { ok: true, re };
457
+ const cause = growsExponentially(re);
458
+ if (cause !== null) {
459
+ return {
460
+ ok: false,
461
+ reason: hasNestedQuantifier(pattern) ? "repeats a group that already repeats, which can take exponential time to match" : "takes time that climbs steeply with the length of the line, which can stall on ordinary text",
462
+ cause
463
+ };
464
+ }
465
+ return { ok: true, re };
466
+ }
467
+ var GUARDED_CACHE_LIMIT = 64;
468
+ var guardedCache = /* @__PURE__ */ new Map();
469
+ function compileGuardedRegexCached(pattern, flags = "") {
470
+ const key = `${flags}/${pattern}`;
471
+ const hit = guardedCache.get(key);
472
+ if (hit !== void 0) return hit;
473
+ const result = compileGuardedRegex(pattern, flags);
474
+ if (guardedCache.size >= GUARDED_CACHE_LIMIT) {
475
+ const oldest = guardedCache.keys().next();
476
+ if (!oldest.done) guardedCache.delete(oldest.value);
477
+ }
478
+ guardedCache.set(key, result);
479
+ return result;
480
+ }
481
+
222
482
  // src/util_config.ts
223
483
  init_define_import_meta_env();
224
- import { readFileSync as readFileSync2 } from "node:fs";
225
- import * as path3 from "node:path";
484
+ import { readFileSync } from "node:fs";
485
+ import * as path2 from "node:path";
486
+ function commandHookFields(h) {
487
+ if (typeof h?.command !== "string") return void 0;
488
+ const args = Array.isArray(h.args) && h.args.every((a) => typeof a === "string") ? h.args : void 0;
489
+ return { command: h.command, args };
490
+ }
491
+ function isOwnHookEntry(h, isOurs) {
492
+ const fields = commandHookFields(h);
493
+ return fields !== void 0 && isOurs(fields.command, fields.args);
494
+ }
226
495
  function stripOwnHooksFromMap(hooks, isOurs) {
227
496
  let removed = false;
228
497
  for (const eventKey of Object.keys(hooks)) {
@@ -231,7 +500,7 @@ function stripOwnHooksFromMap(hooks, isOurs) {
231
500
  const kept = [];
232
501
  for (const group of groups) {
233
502
  const keptHooks = (group.hooks ?? []).filter((h) => {
234
- const isOur = isOurs(h.command, h.args);
503
+ const isOur = isOwnHookEntry(h, isOurs);
235
504
  if (isOur) removed = true;
236
505
  return !isOur;
237
506
  });
@@ -257,7 +526,7 @@ function stripStaleGroupHooks(groups, isOurs, matcherFilter) {
257
526
  next.push(group);
258
527
  continue;
259
528
  }
260
- const keptHooks = (group.hooks ?? []).filter((h) => !isOurs(h.command, h.args));
529
+ const keptHooks = (group.hooks ?? []).filter((h) => !isOwnHookEntry(h, isOurs));
261
530
  if (keptHooks.length > 0) {
262
531
  next.push({ ...group, hooks: keptHooks });
263
532
  } else if ((group.hooks ?? []).length === 0) {
@@ -266,10 +535,13 @@ function stripStaleGroupHooks(groups, isOurs, matcherFilter) {
266
535
  }
267
536
  return next;
268
537
  }
538
+ function detectEol(text) {
539
+ return text.includes("\r\n") ? "\r\n" : "\n";
540
+ }
269
541
  function stripDelimitedBlock(p, beginMarker, endMarker, keepBackups = false) {
270
542
  let existing;
271
543
  try {
272
- existing = readFileSync2(p, "utf8");
544
+ existing = readFileSync(p, "utf8");
273
545
  } catch {
274
546
  return false;
275
547
  }
@@ -279,29 +551,29 @@ function stripDelimitedBlock(p, beginMarker, endMarker, keepBackups = false) {
279
551
  const before = existing.slice(0, beginIdx).replace(/\s+$/, "");
280
552
  const after = existing.slice(endIdx + endMarker.length).replace(/^\s+/, "");
281
553
  let next;
554
+ const eol = detectEol(existing);
282
555
  if (before.length > 0 && after.length > 0) {
283
- next = `${before}
284
-
285
- ${after}`;
556
+ next = `${before}${eol}${eol}${after}`;
286
557
  } else if (before.length > 0) {
287
- next = `${before}
288
- `;
558
+ next = `${before}${eol}`;
289
559
  } else {
290
560
  next = after;
291
561
  }
292
562
  backupFile(p);
293
- atomicWriteText(p, next);
563
+ atomicWriteText(p, keepBom(existing, next));
294
564
  if (!keepBackups) removeCreatedBackups(p);
295
565
  return true;
296
566
  }
297
- function upsertDelimitedBlock(p, beginMarker, endMarker, block) {
567
+ function upsertDelimitedBlock(p, beginMarker, endMarker, blockText) {
298
568
  assertWriteInScope(p);
299
569
  let existing;
300
570
  try {
301
- existing = readFileSync2(p, "utf8");
571
+ existing = readFileSync(p, "utf8");
302
572
  } catch {
303
573
  existing = "";
304
574
  }
575
+ const eol = detectEol(existing);
576
+ const block = eol === "\n" ? blockText : blockText.replace(/\r?\n/g, eol);
305
577
  const beginIdx = existing.indexOf(beginMarker);
306
578
  const endIdx = existing.indexOf(endMarker);
307
579
  if (beginIdx !== -1 && endIdx !== -1 && endIdx > beginIdx) {
@@ -309,42 +581,136 @@ function upsertDelimitedBlock(p, beginMarker, endMarker, block) {
309
581
  const after = existing.slice(endIdx + endMarker.length);
310
582
  const current = existing.slice(beginIdx, endIdx + endMarker.length);
311
583
  if (current === block) return false;
312
- ensureDirSync(path3.dirname(p));
584
+ ensureDirSync(path2.dirname(p));
313
585
  backupFile(p);
314
586
  atomicWriteText(p, `${before}${block}${after}`);
315
587
  return true;
316
588
  }
317
589
  const trimmed = existing.replace(/\s+$/, "");
318
- const next = trimmed.length > 0 ? `${trimmed}
319
-
320
- ${block}
321
- ` : `${block}
322
- `;
323
- ensureDirSync(path3.dirname(p));
590
+ const next = trimmed.length > 0 ? `${trimmed}${eol}${eol}${block}${eol}` : `${block}${eol}`;
591
+ ensureDirSync(path2.dirname(p));
324
592
  backupFile(p);
325
- atomicWriteText(p, next);
593
+ atomicWriteText(p, keepBom(existing, next));
326
594
  return true;
327
595
  }
328
596
  function writeJsonSettings(p, settings) {
329
- ensureDirSync(path3.dirname(p));
597
+ ensureDirSync(path2.dirname(p));
598
+ let existing = "";
599
+ try {
600
+ existing = readFileSync(p, "utf8");
601
+ } catch {
602
+ }
330
603
  backupFile(p);
331
- atomicWriteText(p, `${JSON.stringify(settings, null, 2)}
332
- `);
604
+ const eol = detectEol(existing);
605
+ const body = JSON.stringify(settings, null, detectJsonIndent(existing)).replace(/\n/g, eol);
606
+ atomicWriteText(p, keepBom(existing, existing.length > 0 && !existing.endsWith("\n") ? body : `${body}${eol}`));
607
+ }
608
+ var BOM = String.fromCharCode(65279);
609
+ function keepBom(existing, next) {
610
+ return existing?.startsWith(BOM) && !next.startsWith(BOM) ? `${BOM}${next}` : next;
611
+ }
612
+ function writeConfigText(p, next) {
613
+ let existing;
614
+ try {
615
+ existing = readFileSync(p, "utf8");
616
+ } catch {
617
+ existing = void 0;
618
+ }
619
+ atomicWriteText(p, keepBom(existing, next));
620
+ }
621
+ function detectJsonIndent(text) {
622
+ const lead = /^([ \t]+)\S/m.exec(text)?.[1];
623
+ if (lead === void 0) return " ";
624
+ return lead.startsWith(" ") ? " " : lead.slice(0, 10);
333
625
  }
334
626
  function writeIfDifferent(p, content, backup = false) {
335
627
  let existing;
336
628
  try {
337
- existing = readFileSync2(p, "utf8");
629
+ existing = readFileSync(p, "utf8");
338
630
  } catch {
339
631
  existing = void 0;
340
632
  }
341
633
  if (existing === content) return false;
342
634
  if (backup) backupFile(p);
343
- ensureDirSync(path3.dirname(p));
635
+ ensureDirSync(path2.dirname(p));
344
636
  atomicWriteText(p, content);
345
637
  return true;
346
638
  }
347
639
 
640
+ // src/encoding.ts
641
+ init_define_import_meta_env();
642
+ function stripBom(text) {
643
+ return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
644
+ }
645
+ function detectSourceEncoding(buf) {
646
+ if (buf.length >= 4) {
647
+ if (buf[0] === 255 && buf[1] === 254 && buf[2] === 0 && buf[3] === 0) return "utf32le";
648
+ if (buf[0] === 0 && buf[1] === 0 && buf[2] === 254 && buf[3] === 255) return "utf32be";
649
+ }
650
+ if (buf.length >= 2) {
651
+ if (buf[0] === 255 && buf[1] === 254) return "utf16le";
652
+ if (buf[0] === 254 && buf[1] === 255) return "utf16be";
653
+ }
654
+ if (buf.length >= 3 && buf[0] === 239 && buf[1] === 187 && buf[2] === 191) return "utf8-bom";
655
+ return "utf8";
656
+ }
657
+ function decodeSource(buf) {
658
+ switch (detectSourceEncoding(buf)) {
659
+ case "utf32le":
660
+ return decodeUtf32(buf.subarray(4), true);
661
+ case "utf32be":
662
+ return decodeUtf32(buf.subarray(4), false);
663
+ case "utf16le":
664
+ return buf.subarray(2).toString("utf16le");
665
+ case "utf16be":
666
+ return swap16(buf.subarray(2)).toString("utf16le");
667
+ case "utf8-bom":
668
+ return buf.subarray(3).toString("utf8");
669
+ default:
670
+ return buf.toString("utf8");
671
+ }
672
+ }
673
+ function encodeSource(text, encoding) {
674
+ switch (encoding) {
675
+ case "utf32le":
676
+ return Buffer.concat([Buffer.from([255, 254, 0, 0]), encodeUtf32(text, true)]);
677
+ case "utf32be":
678
+ return Buffer.concat([Buffer.from([0, 0, 254, 255]), encodeUtf32(text, false)]);
679
+ case "utf16le":
680
+ return Buffer.concat([Buffer.from([255, 254]), Buffer.from(text, "utf16le")]);
681
+ case "utf16be":
682
+ return Buffer.concat([Buffer.from([254, 255]), swap16(Buffer.from(text, "utf16le"))]);
683
+ case "utf8-bom":
684
+ return Buffer.concat([Buffer.from([239, 187, 191]), Buffer.from(text, "utf8")]);
685
+ default:
686
+ return Buffer.from(text, "utf8");
687
+ }
688
+ }
689
+ function swap16(buf) {
690
+ const out = Buffer.from(buf);
691
+ return out.subarray(0, out.length - out.length % 2).swap16();
692
+ }
693
+ function decodeUtf32(buf, littleEndian) {
694
+ const points = [];
695
+ for (let i = 0; i + 4 <= buf.length; i += 4) {
696
+ const cp = littleEndian ? buf.readUInt32LE(i) : buf.readUInt32BE(i);
697
+ points.push(cp > 1114111 || cp >= 55296 && cp <= 57343 ? 65533 : cp);
698
+ }
699
+ let out = "";
700
+ for (let i = 0; i < points.length; i += 8192) out += String.fromCodePoint(...points.slice(i, i + 8192));
701
+ return out;
702
+ }
703
+ function encodeUtf32(text, littleEndian) {
704
+ const points = [...text];
705
+ const out = Buffer.alloc(points.length * 4);
706
+ points.forEach((ch, i) => {
707
+ const cp = ch.codePointAt(0) ?? 65533;
708
+ if (littleEndian) out.writeUInt32LE(cp, i * 4);
709
+ else out.writeUInt32BE(cp, i * 4);
710
+ });
711
+ return out;
712
+ }
713
+
348
714
  // src/util.ts
349
715
  function runGit(args, opts = {}) {
350
716
  const subArgs = args[0] === "diff" ? [args[0], "--no-ext-diff", "--no-textconv", ...args.slice(1)] : args;
@@ -387,8 +753,10 @@ function isRetryable(err) {
387
753
  return typeof code === "string" && RETRYABLE_ERRNO.has(code);
388
754
  }
389
755
  function isEExist(err) {
390
- if (typeof err !== "object" || err === null) return false;
391
- return err.code === "EEXIST";
756
+ return errnoCode(err) === "EEXIST";
757
+ }
758
+ function errnoCode(err) {
759
+ return typeof err === "object" && err !== null ? err.code : void 0;
392
760
  }
393
761
  function ensureDirSync(dir) {
394
762
  assertWriteInScope(dir);
@@ -415,10 +783,28 @@ function withRetryOnLock(fn) {
415
783
  }
416
784
  throw lastErr;
417
785
  }
418
- function atomicWriteCore(dest, content) {
419
- assertWriteInScope(dest);
786
+ function resolveSymlinkChain(p) {
787
+ const uid = typeof process.getuid === "function" ? process.getuid() : void 0;
788
+ let current = p;
789
+ for (let hops = 0; hops < 40; hops++) {
790
+ let st;
791
+ try {
792
+ st = lstatSync(current);
793
+ } catch (err) {
794
+ if (err.code === "ENOENT") return current;
795
+ throw err;
796
+ }
797
+ if (!st.isSymbolicLink() || uid !== void 0 && st.uid !== uid && st.uid !== 0) return current;
798
+ current = path3.resolve(path3.dirname(current), readlinkSync(current));
799
+ }
800
+ throw Object.assign(new Error(`ELOOP: too many levels of symbolic links, resolving ${p}`), { code: "ELOOP" });
801
+ }
802
+ function atomicWriteCore(requested, content) {
803
+ assertWriteInScope(requested);
804
+ const dest = resolveSymlinkChain(requested);
805
+ if (dest !== requested) assertWriteInScope(dest);
420
806
  const tmp = `${dest}.${process.pid}.${process.hrtime.bigint().toString()}.tmp`;
421
- ensureDirSync(path4.dirname(dest));
807
+ ensureDirSync(path3.dirname(dest));
422
808
  try {
423
809
  const fd = openSync(tmp, "w", 384);
424
810
  try {
@@ -431,8 +817,8 @@ function atomicWriteCore(dest, content) {
431
817
  closeSync(fd);
432
818
  }
433
819
  try {
434
- const destMode = statSync(dest).mode;
435
- chmodSync(tmp, destMode);
820
+ const destStat = lstatSync(dest);
821
+ if (!destStat.isSymbolicLink()) chmodSync(tmp, destStat.mode);
436
822
  } catch (e) {
437
823
  if (e.code !== "ENOENT") throw e;
438
824
  }
@@ -454,19 +840,19 @@ function atomicWriteBytes(filePath, content) {
454
840
  function installSingleFilePlugin(filePath, sidecarPath, template) {
455
841
  let existing;
456
842
  try {
457
- existing = readFileSync3(filePath, "utf8");
843
+ existing = readFileSync2(filePath, "utf8");
458
844
  } catch {
459
845
  existing = void 0;
460
846
  }
461
847
  const entryPath = process.argv[1];
462
848
  if (entryPath) {
463
- ensureDirSync(path4.dirname(filePath));
849
+ ensureDirSync(path3.dirname(filePath));
464
850
  atomicWriteText(sidecarPath, JSON.stringify({ entryPath }));
465
851
  }
466
852
  if (existing === template) {
467
853
  return { filePath, alreadyInstalled: true };
468
854
  }
469
- ensureDirSync(path4.dirname(filePath));
855
+ ensureDirSync(path3.dirname(filePath));
470
856
  atomicWriteText(filePath, template);
471
857
  return { filePath, alreadyInstalled: false };
472
858
  }
@@ -500,7 +886,7 @@ var MAX_BACKUPS_PER_FILE = 5;
500
886
  var MAX_BACKUP_NAME_ATTEMPTS = 16;
501
887
  function backupFile(p) {
502
888
  assertWriteInScope(p);
503
- if (!existsSync2(p)) return;
889
+ if (!existsSync(p)) return;
504
890
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
505
891
  let backupPath;
506
892
  for (let attempt = 0; ; attempt++) {
@@ -541,6 +927,7 @@ var LOCK_WAIT_MS = 2e3;
541
927
  var LOCK_STALE_MS = 5e3;
542
928
  var LOCK_WAIT_MS_HARDENED = 15e3;
543
929
  var LOCK_LIVE_HOLDER_MAX_MS = 6e4;
930
+ var LOCK_EPERM_RUN_MS = 1e3;
544
931
  function lockHolderAlive(token) {
545
932
  const pid = Number(/^(\d+):/.exec(token)?.[1]);
546
933
  if (!Number.isSafeInteger(pid) || pid <= 0 || pid === process.pid) return false;
@@ -551,33 +938,61 @@ function lockHolderAlive(token) {
551
938
  return err.code === "EPERM";
552
939
  }
553
940
  }
941
+ function lockAbandoned(lockPath, staleMs) {
942
+ const age = Date.now() - statSync(lockPath).mtimeMs;
943
+ return age > staleMs && (age > Math.max(staleMs, LOCK_LIVE_HOLDER_MAX_MS) || !lockHolderAlive(readFileSync2(lockPath, "utf8")));
944
+ }
945
+ function stealAbandoned(lockPath, staleMs) {
946
+ const guardPath = `${lockPath}.steal`;
947
+ try {
948
+ writeFileSync(guardPath, "", { flag: "wx" });
949
+ } catch (err) {
950
+ try {
951
+ if (isEExist(err) && Date.now() - statSync(guardPath).mtimeMs > staleMs) unlinkSync(guardPath);
952
+ } catch {
953
+ }
954
+ return false;
955
+ }
956
+ try {
957
+ if (lockAbandoned(lockPath, staleMs)) unlinkSync(lockPath);
958
+ } catch {
959
+ } finally {
960
+ try {
961
+ unlinkSync(guardPath);
962
+ } catch {
963
+ }
964
+ }
965
+ return true;
966
+ }
554
967
  function withFileLock(lockPath, fn, opts = {}) {
555
968
  const waitMs = opts.waitMs ?? LOCK_WAIT_MS;
556
969
  const staleMs = opts.staleMs ?? LOCK_STALE_MS;
557
970
  const token = `${process.pid}:${process.hrtime.bigint().toString()}`;
558
971
  const deadline = Date.now() + waitMs;
559
972
  let attempt = 0;
973
+ let epermSince;
560
974
  for (; ; ) {
561
975
  try {
562
976
  writeFileSync(lockPath, token, { flag: "wx" });
563
977
  break;
564
978
  } catch (err) {
979
+ if (process.platform === "win32" && errnoCode(err) === "EPERM") {
980
+ epermSince ??= Date.now();
981
+ if (Date.now() >= deadline || Date.now() - epermSince >= LOCK_EPERM_RUN_MS) return void 0;
982
+ sleepSync(Math.min(20 * ++attempt, 200));
983
+ continue;
984
+ }
565
985
  if (!isEExist(err)) return void 0;
986
+ epermSince = void 0;
566
987
  }
567
988
  let stale;
568
989
  try {
569
- const age = Date.now() - statSync(lockPath).mtimeMs;
570
- stale = age > staleMs && (age > Math.max(staleMs, LOCK_LIVE_HOLDER_MAX_MS) || !lockHolderAlive(readFileSync3(lockPath, "utf8")));
571
- } catch {
572
- stale = true;
573
- }
574
- if (stale) {
575
- try {
576
- unlinkSync(lockPath);
577
- } catch {
578
- }
579
- continue;
990
+ stale = lockAbandoned(lockPath, staleMs);
991
+ } catch (err) {
992
+ if (errnoCode(err) === "ENOENT") continue;
993
+ stale = false;
580
994
  }
995
+ if (stale && stealAbandoned(lockPath, staleMs)) continue;
581
996
  if (Date.now() >= deadline) return void 0;
582
997
  sleepSync(Math.min(20 * ++attempt, 200));
583
998
  }
@@ -585,7 +1000,7 @@ function withFileLock(lockPath, fn, opts = {}) {
585
1000
  return fn();
586
1001
  } finally {
587
1002
  try {
588
- if (readFileSync3(lockPath, "utf8") === token) unlinkSync(lockPath);
1003
+ if (readFileSync2(lockPath, "utf8") === token) unlinkSync(lockPath);
589
1004
  } catch {
590
1005
  }
591
1006
  }
@@ -643,9 +1058,9 @@ function redactUrlQuery(raw) {
643
1058
  }
644
1059
  function withExtension(filePath, format) {
645
1060
  const ext = format === "jpeg" ? ".jpg" : `.${format}`;
646
- const dir = path4.dirname(filePath);
647
- const base = path4.basename(filePath, path4.extname(filePath));
648
- return path4.join(dir, `${base}${ext}`);
1061
+ const dir = path3.dirname(filePath);
1062
+ const base = path3.basename(filePath, path3.extname(filePath));
1063
+ return path3.join(dir, `${base}${ext}`);
649
1064
  }
650
1065
  function ensureNewline(text) {
651
1066
  return text.endsWith("\n") ? text : text + "\n";
@@ -704,10 +1119,10 @@ function isTestFile(p) {
704
1119
  }
705
1120
  function isUnderBlockedRoot(filePath, blockedRoots) {
706
1121
  if (blockedRoots.length === 0) return false;
707
- const target = foldPath(normalizePath(path4.resolve(filePath)));
1122
+ const target = foldPath(normalizePath(path3.resolve(filePath)));
708
1123
  for (const root of blockedRoots) {
709
1124
  if (!root) continue;
710
- const normRoot = foldPath(normalizePath(path4.resolve(root)));
1125
+ const normRoot = foldPath(normalizePath(path3.resolve(root)));
711
1126
  if (target === normRoot) return true;
712
1127
  const boundary = normRoot.endsWith("/") ? normRoot : `${normRoot}/`;
713
1128
  if (target.startsWith(boundary)) return true;
@@ -740,21 +1155,158 @@ function hookPowershellCommand(scriptPath, event) {
740
1155
  return `${quotePowershellPath(process.execPath)} ${quotePowershellPath(scriptPath)} ${event}${entryArg}`;
741
1156
  }
742
1157
 
1158
+ // src/bridges/created_configs.ts
1159
+ function ledgerPath() {
1160
+ return path4.join(dataDir(), "created-configs.json");
1161
+ }
1162
+ function keyOf(filePath) {
1163
+ return normalizePath(path4.resolve(filePath));
1164
+ }
1165
+ function foldKey(key) {
1166
+ return foldPath(key);
1167
+ }
1168
+ function readLedger() {
1169
+ try {
1170
+ const parsed = JSON.parse(fs.readFileSync(ledgerPath(), "utf8"));
1171
+ return Array.isArray(parsed) ? parsed.filter((entry) => typeof entry === "string") : [];
1172
+ } catch {
1173
+ return [];
1174
+ }
1175
+ }
1176
+ function writeLedger(entries) {
1177
+ try {
1178
+ ensureDirSync(path4.dirname(ledgerPath()));
1179
+ atomicWriteText(ledgerPath(), `${JSON.stringify(entries)}
1180
+ `);
1181
+ } catch {
1182
+ }
1183
+ }
1184
+ function recordCreatedConfig(filePath) {
1185
+ const key = keyOf(filePath);
1186
+ const entries = readLedger();
1187
+ if (entries.some((entry) => foldKey(entry) === foldKey(key))) return;
1188
+ writeLedger([...entries, key]);
1189
+ }
1190
+ function hasCreatedConfig(filePath) {
1191
+ const key = foldKey(keyOf(filePath));
1192
+ return readLedger().some((entry) => foldKey(entry) === key);
1193
+ }
1194
+ function takeCreatedConfig(filePath) {
1195
+ const key = foldKey(keyOf(filePath));
1196
+ const entries = readLedger();
1197
+ if (!entries.some((entry) => foldKey(entry) === key)) return false;
1198
+ writeLedger(entries.filter((entry) => foldKey(entry) !== key));
1199
+ return true;
1200
+ }
1201
+ function rootKeyMarker(filePath, rootKey) {
1202
+ return `${filePath}#root-key=${rootKey}`;
1203
+ }
1204
+ function recordCreatedRootKey(filePath, rootKey) {
1205
+ recordCreatedConfig(rootKeyMarker(filePath, rootKey));
1206
+ }
1207
+ function takeCreatedRootKey(filePath, rootKey) {
1208
+ return takeCreatedConfig(rootKeyMarker(filePath, rootKey));
1209
+ }
1210
+ function recordCreatedBackup(backupPath) {
1211
+ recordCreatedConfig(backupPath);
1212
+ }
1213
+ function forgetCreatedBackup(backupPath) {
1214
+ takeCreatedConfig(backupPath);
1215
+ }
1216
+ function createdBackupsFor(configPath) {
1217
+ const prefix = foldKey(`${keyOf(configPath)}.bak.`);
1218
+ return readLedger().filter((entry) => foldKey(entry).startsWith(prefix)).sort();
1219
+ }
1220
+ function removeCreatedBackups(configPath) {
1221
+ const prefix = foldKey(`${keyOf(configPath)}.bak.`);
1222
+ const entries = readLedger();
1223
+ const ours = entries.filter((entry) => foldKey(entry).startsWith(prefix));
1224
+ if (ours.length === 0) return 0;
1225
+ const failed = /* @__PURE__ */ new Set();
1226
+ let removed = 0;
1227
+ for (const target of ours) {
1228
+ try {
1229
+ if (fs.existsSync(target) && removeFileInScope(target)) {
1230
+ removed++;
1231
+ }
1232
+ } catch {
1233
+ failed.add(target);
1234
+ }
1235
+ }
1236
+ writeLedger(entries.filter((entry) => !ours.includes(entry) || failed.has(entry)));
1237
+ return removed;
1238
+ }
1239
+ function ensureDirRecordingCreation(dir) {
1240
+ const existed = fs.existsSync(dir);
1241
+ ensureDirSync(dir);
1242
+ if (!existed) recordCreatedConfig(dir);
1243
+ }
1244
+ function holdsNothing(text) {
1245
+ const trimmed = text.trim();
1246
+ return trimmed === "" || /^\{\s*\}$/.test(trimmed);
1247
+ }
1248
+ function removeCreatedIfEmpty(target) {
1249
+ if (!hasCreatedConfig(target)) return;
1250
+ let removed = false;
1251
+ try {
1252
+ removed = fs.lstatSync(target).isDirectory() ? removeEmptyDirInScope(target) : holdsNothing(fs.readFileSync(target, "utf8")) && removeFileInScope(target);
1253
+ } catch {
1254
+ }
1255
+ if (removed) takeCreatedConfig(target);
1256
+ }
1257
+ function recordCreatedBy(targets, work) {
1258
+ const absent = /* @__PURE__ */ new Set();
1259
+ for (const target of targets) {
1260
+ for (let p = path4.resolve(target); !fs.existsSync(p) && !absent.has(p); p = path4.dirname(p)) absent.add(p);
1261
+ }
1262
+ try {
1263
+ return work();
1264
+ } finally {
1265
+ for (const p of absent) if (fs.existsSync(p)) recordCreatedConfig(p);
1266
+ }
1267
+ }
1268
+ function removeCreatedTree(targets) {
1269
+ const paths = /* @__PURE__ */ new Set();
1270
+ for (const target of targets) {
1271
+ for (let p = path4.resolve(target); !paths.has(p); p = path4.dirname(p)) {
1272
+ paths.add(p);
1273
+ if (path4.dirname(p) === p) break;
1274
+ }
1275
+ }
1276
+ for (const p of [...paths].sort((a, b) => b.length - a.length)) {
1277
+ if (fs.existsSync(p)) removeCreatedIfEmpty(p);
1278
+ else if (hasCreatedConfig(p)) takeCreatedConfig(p);
1279
+ }
1280
+ }
1281
+
743
1282
  export {
744
1283
  recordCreatedConfig,
745
1284
  hasCreatedConfig,
746
1285
  takeCreatedConfig,
1286
+ recordCreatedRootKey,
1287
+ takeCreatedRootKey,
747
1288
  removeCreatedBackups,
1289
+ ensureDirRecordingCreation,
1290
+ removeCreatedIfEmpty,
1291
+ recordCreatedBy,
1292
+ removeCreatedTree,
748
1293
  assertProjectScopeTarget,
749
1294
  withInstallScope,
750
1295
  projectScopeRoot,
751
1296
  assertWriteInScope,
752
1297
  projectPathIsConsultable,
1298
+ hasNestedQuantifier,
1299
+ growsExponentially,
1300
+ compileGuardedRegex,
1301
+ compileGuardedRegexCached,
1302
+ commandHookFields,
1303
+ isOwnHookEntry,
753
1304
  stripOwnHooksFromMap,
754
1305
  stripStaleGroupHooks,
755
1306
  stripDelimitedBlock,
756
1307
  upsertDelimitedBlock,
757
1308
  writeJsonSettings,
1309
+ writeConfigText,
758
1310
  writeIfDifferent,
759
1311
  stripBom,
760
1312
  detectSourceEncoding,