@wrongstack/core 0.310.1 → 0.313.1

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 (187) hide show
  1. package/dist/chronicle/index.js +84 -6391
  2. package/dist/chronicle/project-server.js +84 -4868
  3. package/dist/chunk-2BUUIMQB.js +225 -0
  4. package/dist/chunk-2FK4WTFF.js +207 -0
  5. package/dist/chunk-2FQL4PDC.js +292 -0
  6. package/dist/chunk-2KKODIQU.js +2256 -0
  7. package/dist/chunk-2YU4WVBW.js +134 -0
  8. package/dist/chunk-3E244UDA.js +356 -0
  9. package/dist/chunk-3XPVB7BA.js +135 -0
  10. package/dist/chunk-4LJJYBAU.js +388 -0
  11. package/dist/chunk-4VWO3ZXL.js +342 -0
  12. package/dist/chunk-4XV6IR37.js +187 -0
  13. package/dist/chunk-4ZHTKJHM.js +183 -0
  14. package/dist/chunk-52RTVH4M.js +361 -0
  15. package/dist/chunk-57GEWK5X.js +26 -0
  16. package/dist/chunk-5DSMEVA4.js +931 -0
  17. package/dist/chunk-5RP3QTRL.js +1223 -0
  18. package/dist/chunk-5S437PRC.js +50 -0
  19. package/dist/chunk-5XDUGTKN.js +511 -0
  20. package/dist/chunk-62V2AFVG.js +422 -0
  21. package/dist/chunk-65RDIOR2.js +2470 -0
  22. package/dist/chunk-6AKOTGLM.js +597 -0
  23. package/dist/chunk-7ZHZE5EO.js +28 -0
  24. package/dist/chunk-A455ATZB.js +140 -0
  25. package/dist/chunk-AD7ZFZCS.js +46 -0
  26. package/dist/chunk-AI4LLQ2U.js +856 -0
  27. package/dist/chunk-ASX6AW36.js +789 -0
  28. package/dist/chunk-AT4V4XGI.js +3522 -0
  29. package/dist/chunk-AWNQ6ED6.js +311 -0
  30. package/dist/chunk-B4AMLZPB.js +9 -0
  31. package/dist/chunk-BAKVJLEV.js +417 -0
  32. package/dist/chunk-BJHVULHO.js +55 -0
  33. package/dist/chunk-CB2HFKTP.js +9 -0
  34. package/dist/chunk-CE4ZOCOI.js +1640 -0
  35. package/dist/chunk-CQQL4ZOQ.js +151 -0
  36. package/dist/chunk-DEIQMBD2.js +65 -0
  37. package/dist/chunk-E6I5RXVK.js +58 -0
  38. package/dist/chunk-EFEHDQGY.js +1589 -0
  39. package/dist/chunk-EODDVJBM.js +82 -0
  40. package/dist/chunk-EPC3GZD4.js +308 -0
  41. package/dist/chunk-FAYRX2AD.js +13 -0
  42. package/dist/chunk-FFSX2QDQ.js +362 -0
  43. package/dist/chunk-FHAMQS7Q.js +5856 -0
  44. package/dist/chunk-FIV4IJL7.js +2263 -0
  45. package/dist/chunk-FNXVT7HF.js +52 -0
  46. package/dist/chunk-FSWCWSTS.js +395 -0
  47. package/dist/chunk-FW5LDDMJ.js +16464 -0
  48. package/dist/chunk-FXQLIX3K.js +211 -0
  49. package/dist/chunk-G5AAKEEZ.js +228 -0
  50. package/dist/chunk-G5S3S5ZN.js +38 -0
  51. package/dist/chunk-GAZEWQEZ.js +231 -0
  52. package/dist/chunk-GFJOMSHG.js +125 -0
  53. package/dist/chunk-GFXZTHNI.js +158 -0
  54. package/dist/chunk-GM54GJBU.js +960 -0
  55. package/dist/chunk-GPQ3NJPR.js +900 -0
  56. package/dist/chunk-GTCU6DZ3.js +1 -0
  57. package/dist/chunk-H5E77KUJ.js +15 -0
  58. package/dist/chunk-H72H4XDU.js +1023 -0
  59. package/dist/chunk-HA4ZYA6T.js +178 -0
  60. package/dist/chunk-I45KAW2N.js +5020 -0
  61. package/dist/chunk-IQ35HMQL.js +1396 -0
  62. package/dist/chunk-IYFBFX34.js +86 -0
  63. package/dist/chunk-JJPMWPB6.js +109 -0
  64. package/dist/chunk-JTHKOYWU.js +663 -0
  65. package/dist/chunk-JVGPR3TS.js +365 -0
  66. package/dist/chunk-JVKB2TBL.js +48 -0
  67. package/dist/chunk-JX7VBZDK.js +31 -0
  68. package/dist/chunk-K3G6JBUC.js +5232 -0
  69. package/dist/chunk-K4YUNKU7.js +589 -0
  70. package/dist/chunk-KBZGE6LN.js +710 -0
  71. package/dist/chunk-KDQJCT2J.js +45 -0
  72. package/dist/chunk-KI4L2DUL.js +560 -0
  73. package/dist/chunk-KJ2ZTQSL.js +47 -0
  74. package/dist/chunk-KSJ5UTP7.js +154 -0
  75. package/dist/chunk-LHOA5DWA.js +28 -0
  76. package/dist/chunk-LX5QWLBL.js +27 -0
  77. package/dist/chunk-LZDDLNCZ.js +279 -0
  78. package/dist/chunk-M2WF6AXG.js +115 -0
  79. package/dist/chunk-M7BS2K6U.js +1 -0
  80. package/dist/chunk-NDBIPFNY.js +102 -0
  81. package/dist/chunk-NEMIWEXC.js +1199 -0
  82. package/dist/chunk-NFAYHPRH.js +323 -0
  83. package/dist/chunk-O37BQ65S.js +21 -0
  84. package/dist/chunk-O74MJHXU.js +187 -0
  85. package/dist/chunk-OJZEX73F.js +112 -0
  86. package/dist/chunk-PAAWLLZX.js +74 -0
  87. package/dist/chunk-PFXFQQRT.js +339 -0
  88. package/dist/chunk-PFZO3C6H.js +14 -0
  89. package/dist/chunk-PHH7LD45.js +113 -0
  90. package/dist/chunk-QRTG4XTI.js +188 -0
  91. package/dist/chunk-QVOVMXJR.js +1351 -0
  92. package/dist/chunk-RCQYT2I4.js +757 -0
  93. package/dist/chunk-RD6DEE36.js +1178 -0
  94. package/dist/chunk-RJIZEJ42.js +30 -0
  95. package/dist/chunk-RPOA7IAE.js +150 -0
  96. package/dist/chunk-SN2DQRL6.js +1172 -0
  97. package/dist/chunk-SQJVFEBV.js +41 -0
  98. package/dist/chunk-SQP64RCS.js +5391 -0
  99. package/dist/chunk-SVT4RNTR.js +49 -0
  100. package/dist/chunk-SWUFN7XM.js +43 -0
  101. package/dist/chunk-SXMVYC5H.js +174 -0
  102. package/dist/chunk-SZ6AYUIZ.js +23 -0
  103. package/dist/chunk-T3KGZBU5.js +3171 -0
  104. package/dist/chunk-TBRL2RCC.js +9 -0
  105. package/dist/chunk-TRT2HRWZ.js +18 -0
  106. package/dist/chunk-TYW2GI5I.js +1077 -0
  107. package/dist/chunk-UIWONWVG.js +4959 -0
  108. package/dist/chunk-VB3H5WWB.js +151 -0
  109. package/dist/chunk-W4A6QA3D.js +258 -0
  110. package/dist/chunk-WBPVKEEE.js +227 -0
  111. package/dist/chunk-WEBMSQP2.js +123 -0
  112. package/dist/chunk-WOEZV3Q4.js +333 -0
  113. package/dist/chunk-WQQON3SV.js +473 -0
  114. package/dist/chunk-WQTOVMGV.js +119 -0
  115. package/dist/chunk-WZO23AWO.js +2779 -0
  116. package/dist/chunk-XBDP4QPW.js +7 -0
  117. package/dist/chunk-XEBHSJLT.js +103 -0
  118. package/dist/chunk-XQ2ECNK3.js +1 -0
  119. package/dist/chunk-XQ2XGIBF.js +2086 -0
  120. package/dist/chunk-Y2GE5TSI.js +355 -0
  121. package/dist/chunk-YBUJCZ57.js +351 -0
  122. package/dist/chunk-YNCVSFGF.js +149 -0
  123. package/dist/chunk-YUPMXOGP.js +282 -0
  124. package/dist/chunk-YY6APYUM.js +49 -0
  125. package/dist/chunk-Z2IJUO45.js +691 -0
  126. package/dist/chunk-ZEHUCJHY.js +129 -0
  127. package/dist/chunk-ZYU2YOJ6.js +1496 -0
  128. package/dist/chunk-ZZ4V3WIZ.js +163 -0
  129. package/dist/coordination/agents/index.js +145 -6260
  130. package/dist/coordination/index.js +365 -34323
  131. package/dist/coordination/mailbox-project-server.js +48 -3220
  132. package/dist/coordination/mailbox-types.d.ts +13 -1
  133. package/dist/coordination/provider-status-tracker.d.ts +4 -0
  134. package/dist/coordination/sqlite-mailbox.d.ts +2 -1
  135. package/dist/core/agent.d.ts +14 -1
  136. package/dist/core/index.js +267 -12479
  137. package/dist/core/model-ref.js +5 -23
  138. package/dist/core/provider-runner.d.ts +36 -1
  139. package/dist/design/index.js +50 -1087
  140. package/dist/execution/index.d.ts +1 -1
  141. package/dist/execution/index.js +1599 -21887
  142. package/dist/execution/prompt-enhancer.js +16 -535
  143. package/dist/execution/retry-policy.d.ts +31 -1
  144. package/dist/extension/index.js +7 -311
  145. package/dist/goal/index.js +33 -3435
  146. package/dist/hooks/index.js +14 -1138
  147. package/dist/hq/index.js +112 -5139
  148. package/dist/hq/protocol.js +21 -668
  149. package/dist/index.js +1410 -92655
  150. package/dist/infrastructure/index.js +64 -4811
  151. package/dist/kernel/events/provider-events.d.ts +15 -0
  152. package/dist/kernel/events/wrongtrace-events.d.ts +26 -0
  153. package/dist/kernel/events.d.ts +16 -7
  154. package/dist/kernel/index.js +14 -992
  155. package/dist/models/index.js +40 -1117
  156. package/dist/notifications/index.js +3 -108
  157. package/dist/observability/index.js +17 -279
  158. package/dist/plugin/index.js +584 -14835
  159. package/dist/prompts/index.js +14 -948
  160. package/dist/registry/index.js +9 -822
  161. package/dist/registry-R23UBE7H.js +14 -0
  162. package/dist/replay/index.js +6 -84
  163. package/dist/review-finding-store-DKAV3AS6.js +21 -0
  164. package/dist/review-report-store-OWY3EC3N.js +19 -0
  165. package/dist/security/index.js +114 -2202
  166. package/dist/session-catalog/index.js +36 -2103
  167. package/dist/session-catalog/project-server.js +42 -1435
  168. package/dist/skills/index.js +35 -1578
  169. package/dist/storage/index.js +182 -15600
  170. package/dist/tasking/index.js +10 -676
  171. package/dist/tools/index.js +52 -9589
  172. package/dist/types/config/autonomy.d.ts +5 -0
  173. package/dist/types/config/tools.d.ts +2 -2
  174. package/dist/types/config/ui.d.ts +1 -1
  175. package/dist/types/errors.d.ts +18 -0
  176. package/dist/types/index.js +121 -1341
  177. package/dist/types/provider-runner.d.ts +8 -0
  178. package/dist/types/session-markers.js +8 -144
  179. package/dist/utils/error.js +3 -4
  180. package/dist/utils/expect-defined.js +3 -9
  181. package/dist/utils/heap-watchdog.js +6 -706
  182. package/dist/utils/index.js +269 -5685
  183. package/dist/utils/sage-output-block.js +5 -42
  184. package/dist/wiring/proxy-rewrite.d.ts +92 -4
  185. package/dist/wiring/proxy-rewrite.js +20 -61
  186. package/dist/worktree/index.js +6 -887
  187. package/package.json +4 -4
@@ -0,0 +1,422 @@
1
+ import {
2
+ mapWithConcurrency
3
+ } from "./chunk-SZ6AYUIZ.js";
4
+ import {
5
+ DEFAULT_WALK_IGNORE_DIRS,
6
+ watchProjectTree
7
+ } from "./chunk-TYW2GI5I.js";
8
+
9
+ // src/chronicle/context.ts
10
+ import { randomUUID } from "node:crypto";
11
+ function createChronicleContext(scope, traceId = randomUUID()) {
12
+ return {
13
+ scope: { ...scope },
14
+ correlation: { traceId, spanId: randomUUID() }
15
+ };
16
+ }
17
+ function childChronicleContext(parent, overrides = {}) {
18
+ return {
19
+ scope: { ...parent.scope, ...overrides.scope },
20
+ correlation: {
21
+ ...parent.correlation,
22
+ ...overrides.correlation,
23
+ traceId: parent.correlation.traceId,
24
+ parentSpanId: parent.correlation.spanId,
25
+ spanId: overrides.correlation?.spanId ?? randomUUID()
26
+ }
27
+ };
28
+ }
29
+
30
+ // src/chronicle/file-observer.ts
31
+ import { createHash } from "node:crypto";
32
+ import * as fsp from "node:fs/promises";
33
+ import * as path from "node:path";
34
+ var DEFAULT_EXCLUDED = [
35
+ ...DEFAULT_WALK_IGNORE_DIRS,
36
+ ".wrongstack",
37
+ ".claude",
38
+ ".temp_files"
39
+ ];
40
+ var SCAN_HASH_CONCURRENCY = 32;
41
+ var DEFAULT_FULL_RESCAN_MIN_INTERVAL_MS = 3e4;
42
+ var MAX_RECENT_TOOL_MUTATIONS = 500;
43
+ async function startChronicleFileObserver(options) {
44
+ const root = path.resolve(options.projectRoot);
45
+ const excluded = new Set(options.excludedDirectories ?? DEFAULT_EXCLUDED);
46
+ const excludedPaths = normalizeExcludedPaths(root, options.excludedPaths ?? []);
47
+ const debounceMs = options.debounceMs ?? 120;
48
+ const maxHashBytes = options.maxHashBytes ?? 8 * 1024 * 1024;
49
+ const known = (await scanProject(root, excluded, excludedPaths, maxHashBytes, options.onError)).files;
50
+ const recentToolMutations = /* @__PURE__ */ new Map();
51
+ const noteToolMutation = (hint) => {
52
+ const absolute = path.isAbsolute(hint.path) ? path.normalize(hint.path) : path.resolve(root, hint.path);
53
+ const relative2 = normalizeRelative(path.relative(root, absolute));
54
+ if (relative2.startsWith("../") || isExcluded(relative2, excluded, excludedPaths)) return;
55
+ recentToolMutations.set(relative2, {
56
+ at: hint.at ?? Date.now(),
57
+ toolUseId: hint.toolUseId,
58
+ toolName: hint.toolName,
59
+ agentId: hint.agentId,
60
+ sessionId: hint.sessionId
61
+ });
62
+ if (recentToolMutations.size > MAX_RECENT_TOOL_MUTATIONS) {
63
+ const overflow = recentToolMutations.size - MAX_RECENT_TOOL_MUTATIONS;
64
+ const keys = [...recentToolMutations.keys()];
65
+ for (let i = 0; i < overflow && i < keys.length; i++) {
66
+ recentToolMutations.delete(keys[i]);
67
+ }
68
+ }
69
+ };
70
+ const offToolProgress = options.events?.on("tool.progress", (event) => {
71
+ if (event.event.type !== "file_changed" || !event.event.path) return;
72
+ noteToolMutation({
73
+ path: event.event.path,
74
+ toolUseId: event.id,
75
+ toolName: event.name,
76
+ agentId: event.agentId,
77
+ sessionId: event.sessionId
78
+ });
79
+ });
80
+ const pending = /* @__PURE__ */ new Set();
81
+ let timer;
82
+ let closed = false;
83
+ let flushTail = null;
84
+ const minFullRescanIntervalMs = options.minFullRescanIntervalMs ?? DEFAULT_FULL_RESCAN_MIN_INTERVAL_MS;
85
+ let lastFullScanAt = Date.now();
86
+ let fullRescanTimer;
87
+ const bumpDebounce = () => {
88
+ if (timer) clearTimeout(timer);
89
+ timer = setTimeout(() => {
90
+ timer = void 0;
91
+ drainPending();
92
+ }, debounceMs);
93
+ };
94
+ const requestFullRescan = () => {
95
+ if (closed) return;
96
+ const since = Date.now() - lastFullScanAt;
97
+ if (since >= minFullRescanIntervalMs) {
98
+ pending.add("*");
99
+ bumpDebounce();
100
+ return;
101
+ }
102
+ if (fullRescanTimer) return;
103
+ fullRescanTimer = setTimeout(() => {
104
+ fullRescanTimer = void 0;
105
+ if (closed) return;
106
+ pending.add("*");
107
+ bumpDebounce();
108
+ }, minFullRescanIntervalMs - since);
109
+ if (typeof fullRescanTimer.unref === "function") fullRescanTimer.unref();
110
+ };
111
+ const schedule = (filename) => {
112
+ if (closed) return;
113
+ if (filename === null) {
114
+ requestFullRescan();
115
+ return;
116
+ }
117
+ const relative2 = normalizeRelative(String(filename));
118
+ if (!relative2 || isExcluded(relative2, excluded, excludedPaths)) return;
119
+ pending.add(relative2);
120
+ bumpDebounce();
121
+ };
122
+ const reconcile = async (changedPaths) => {
123
+ const wantsFullScan = changedPaths.includes("*");
124
+ if (wantsFullScan) lastFullScanAt = Date.now();
125
+ const fullScan = wantsFullScan ? await scanProject(root, excluded, excludedPaths, maxHashBytes, options.onError, known) : void 0;
126
+ const candidates = (fullScan ? unionKeys(known, fullScan.files) : changedPaths).filter(
127
+ (relative2) => !isExcluded(relative2, excluded, excludedPaths)
128
+ );
129
+ const changes = [];
130
+ for (const relative2 of candidates) {
131
+ const before = known.get(relative2);
132
+ const cached = fullScan?.files.get(relative2);
133
+ const after = cached ?? (fullScan?.complete ? void 0 : await fingerprint(path.join(root, relative2), maxHashBytes));
134
+ if (sameFingerprint(before, after)) continue;
135
+ changes.push({ relative: relative2, before, after });
136
+ }
137
+ const deleted = changes.filter((change) => change.before && !change.after);
138
+ const created = changes.filter((change) => !change.before && change.after);
139
+ const consumed = /* @__PURE__ */ new Set();
140
+ const journalWrites = [];
141
+ for (const from of deleted) {
142
+ const match = created.find(
143
+ (to) => !consumed.has(to.relative) && from.before?.hash !== void 0 && from.before.hash === to.after?.hash
144
+ );
145
+ if (!match) continue;
146
+ consumed.add(from.relative);
147
+ consumed.add(match.relative);
148
+ known.delete(from.relative);
149
+ known.set(match.relative, match.after);
150
+ journalWrites.push(
151
+ recordMutation(
152
+ options,
153
+ "file.external.renamed",
154
+ match.relative,
155
+ match.after,
156
+ {
157
+ operation: "rename",
158
+ previousPath: from.relative,
159
+ previousResourceId: resourceId(from.relative),
160
+ actor: "external"
161
+ },
162
+ mutationAttribution(match.relative, recentToolMutations)
163
+ )
164
+ );
165
+ }
166
+ for (const change of changes) {
167
+ if (consumed.has(change.relative)) continue;
168
+ if (!change.after) {
169
+ known.delete(change.relative);
170
+ journalWrites.push(
171
+ recordMutation(
172
+ options,
173
+ "file.external.deleted",
174
+ change.relative,
175
+ change.before,
176
+ {
177
+ operation: "delete",
178
+ actor: "external",
179
+ previousHash: change.before?.hash,
180
+ previousSize: change.before?.size
181
+ },
182
+ mutationAttribution(change.relative, recentToolMutations)
183
+ )
184
+ );
185
+ } else if (!change.before) {
186
+ known.set(change.relative, change.after);
187
+ journalWrites.push(
188
+ recordMutation(
189
+ options,
190
+ "file.external.created",
191
+ change.relative,
192
+ change.after,
193
+ {
194
+ operation: "write",
195
+ actor: "external"
196
+ },
197
+ mutationAttribution(change.relative, recentToolMutations)
198
+ )
199
+ );
200
+ } else {
201
+ known.set(change.relative, change.after);
202
+ journalWrites.push(
203
+ recordMutation(
204
+ options,
205
+ "file.external.modified",
206
+ change.relative,
207
+ change.after,
208
+ {
209
+ operation: "edit",
210
+ actor: "external",
211
+ previousHash: change.before.hash,
212
+ previousSize: change.before.size
213
+ },
214
+ mutationAttribution(change.relative, recentToolMutations)
215
+ )
216
+ );
217
+ }
218
+ }
219
+ await Promise.all(journalWrites);
220
+ };
221
+ const drainPending = () => {
222
+ if (flushTail) return flushTail;
223
+ const drain = (async () => {
224
+ while (pending.size > 0) {
225
+ const paths = [...pending];
226
+ pending.clear();
227
+ await reconcile(paths).catch((error) => options.onError?.(error));
228
+ }
229
+ })().finally(() => {
230
+ if (flushTail === drain) flushTail = null;
231
+ if (!closed && pending.size > 0) drainPending();
232
+ });
233
+ flushTail = drain;
234
+ return drain;
235
+ };
236
+ let watcher;
237
+ try {
238
+ watcher = watchProjectTree(root, (event) => schedule(event.filename), {
239
+ onError: (error) => options.onError?.(error)
240
+ });
241
+ } catch (error) {
242
+ options.onError?.(error);
243
+ throw error;
244
+ }
245
+ return {
246
+ get watchedFiles() {
247
+ return known.size;
248
+ },
249
+ noteToolMutation,
250
+ async close() {
251
+ if (closed) return;
252
+ closed = true;
253
+ offToolProgress?.();
254
+ watcher.close();
255
+ if (timer) {
256
+ clearTimeout(timer);
257
+ timer = void 0;
258
+ }
259
+ if (fullRescanTimer) {
260
+ clearTimeout(fullRescanTimer);
261
+ fullRescanTimer = void 0;
262
+ }
263
+ if (pending.size > 0) drainPending();
264
+ await flushTail;
265
+ recentToolMutations.clear();
266
+ }
267
+ };
268
+ }
269
+ async function recordMutation(options, eventType, relativePath, state, attributes, attribution) {
270
+ const context = typeof options.context === "function" ? options.context() : options.context;
271
+ const operation = attributes["operation"];
272
+ options.events?.emit("file.activity", {
273
+ filePath: path.join(options.projectRoot, relativePath),
274
+ operation,
275
+ phase: "changed",
276
+ source: attribution ? "tool" : "external",
277
+ at: Date.now(),
278
+ sessionId: context.scope.sessionId,
279
+ traceId: context.correlation.traceId,
280
+ agentId: attribution?.agentId ?? context.scope.agentId,
281
+ ...attribution ? { toolUseId: attribution.toolUseId, toolName: attribution.toolName } : {}
282
+ });
283
+ const input = {
284
+ eventType: attribution ? eventType.replace(".external.", ".tool.") : eventType,
285
+ scope: {
286
+ ...context.scope,
287
+ ...attribution?.sessionId ? { sessionId: attribution.sessionId } : {},
288
+ ...attribution?.agentId ? { agentId: attribution.agentId } : {}
289
+ },
290
+ correlation: {
291
+ ...context.correlation,
292
+ ...attribution ? { toolCallId: attribution.toolUseId } : {}
293
+ },
294
+ outcome: "success",
295
+ resource: {
296
+ kind: "file",
297
+ id: resourceId(relativePath),
298
+ path: normalizeRelative(relativePath),
299
+ ...state?.hash ? { contentHashAfter: state.hash } : {}
300
+ },
301
+ attributes: {
302
+ ...attributes,
303
+ actor: attribution ? "agent" : attributes["actor"],
304
+ source: attribution ? "tool" : "external",
305
+ toolName: attribution?.toolName,
306
+ size: state?.size,
307
+ mtimeMs: state?.mtimeMs,
308
+ observedBy: "fs.watch"
309
+ }
310
+ };
311
+ await options.journal.append(input);
312
+ }
313
+ function mutationAttribution(relativePath, recent) {
314
+ const value = recent.get(relativePath);
315
+ if (!value) return void 0;
316
+ recent.delete(relativePath);
317
+ return Date.now() - value.at <= 2e3 ? value : void 0;
318
+ }
319
+ async function scanProject(root, excluded, excludedPaths, maxHashBytes, onError, previous) {
320
+ const result = /* @__PURE__ */ new Map();
321
+ const dirs = [""];
322
+ let complete = true;
323
+ while (dirs.length > 0) {
324
+ const relativeDir = dirs.pop();
325
+ try {
326
+ const entries = await fsp.readdir(path.join(root, relativeDir), { withFileTypes: true });
327
+ const filePaths = [];
328
+ for (const entry of entries) {
329
+ const relative2 = normalizeRelative(path.join(relativeDir, entry.name));
330
+ if (isExcluded(relative2, excluded, excludedPaths)) continue;
331
+ if (entry.isDirectory()) {
332
+ dirs.push(relative2);
333
+ } else if (entry.isFile()) {
334
+ filePaths.push(relative2);
335
+ }
336
+ }
337
+ const fingerprints = await mapWithConcurrency(
338
+ filePaths,
339
+ SCAN_HASH_CONCURRENCY,
340
+ async (relative2) => {
341
+ try {
342
+ const value = await fingerprint(
343
+ path.join(root, relative2),
344
+ maxHashBytes,
345
+ previous?.get(relative2)
346
+ );
347
+ return value ? [relative2, value] : null;
348
+ } catch (error) {
349
+ complete = false;
350
+ onError?.(error);
351
+ return null;
352
+ }
353
+ }
354
+ );
355
+ for (const entry of fingerprints) {
356
+ if (entry) result.set(entry[0], entry[1]);
357
+ }
358
+ } catch (error) {
359
+ complete = false;
360
+ onError?.(error);
361
+ }
362
+ }
363
+ return { files: result, complete };
364
+ }
365
+ async function fingerprint(filePath, maxHashBytes, previous) {
366
+ try {
367
+ const stat2 = await fsp.stat(filePath);
368
+ if (!stat2.isFile()) return void 0;
369
+ const base = { size: stat2.size, mtimeMs: stat2.mtimeMs };
370
+ if (previous?.hash !== void 0 && previous.size === stat2.size && previous.mtimeMs === stat2.mtimeMs) {
371
+ base.hash = previous.hash;
372
+ return base;
373
+ }
374
+ if (stat2.size <= maxHashBytes) {
375
+ base.hash = createHash("sha256").update(await fsp.readFile(filePath)).digest("hex");
376
+ }
377
+ return base;
378
+ } catch (error) {
379
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT")
380
+ return void 0;
381
+ throw error;
382
+ }
383
+ }
384
+ function sameFingerprint(a, b) {
385
+ if (!a || !b) return a === b;
386
+ if (a.hash !== void 0 && b.hash !== void 0) return a.hash === b.hash;
387
+ return a.size === b.size && a.mtimeMs === b.mtimeMs;
388
+ }
389
+ function isExcluded(relative2, excluded, excludedPaths) {
390
+ const normalized = normalizeRelative(relative2);
391
+ if (normalized.split("/").some((segment) => excluded.has(segment))) return true;
392
+ for (const prefix of excludedPaths) {
393
+ if (normalized === prefix || normalized.startsWith(`${prefix}/`)) return true;
394
+ }
395
+ return false;
396
+ }
397
+ function normalizeExcludedPaths(root, values) {
398
+ const result = /* @__PURE__ */ new Set();
399
+ for (const value of values) {
400
+ const relative2 = path.isAbsolute(value) ? path.relative(root, path.resolve(value)) : value;
401
+ const normalized = normalizeRelative(relative2).replace(/\/+$/u, "");
402
+ if (!normalized || normalized === "." || normalized.startsWith("../")) continue;
403
+ result.add(normalized);
404
+ }
405
+ return result;
406
+ }
407
+ function normalizeRelative(value) {
408
+ return value.replaceAll("\\", "/").replace(/^\.\//, "");
409
+ }
410
+ function resourceId(relativePath) {
411
+ return `file_${createHash("sha256").update(normalizeRelative(relativePath)).digest("hex").slice(0, 24)}`;
412
+ }
413
+ function unionKeys(a, b) {
414
+ return [.../* @__PURE__ */ new Set([...a.keys(), ...b.keys()])];
415
+ }
416
+
417
+ export {
418
+ createChronicleContext,
419
+ childChronicleContext,
420
+ startChronicleFileObserver
421
+ };
422
+ //# sourceMappingURL=chunk-62V2AFVG.js.map