codesesh 1.0.3 → 1.0.5

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 (66) hide show
  1. package/README.md +22 -14
  2. package/dist/chunk-FCYCBGEL.js +670 -0
  3. package/dist/chunk-FCYCBGEL.js.map +1 -0
  4. package/dist/chunk-NBJJGH5P.js +2053 -0
  5. package/dist/chunk-NBJJGH5P.js.map +1 -0
  6. package/dist/chunk-PAP2Q3WV.js +1271 -0
  7. package/dist/chunk-PAP2Q3WV.js.map +1 -0
  8. package/dist/chunk-QH2HOXJH.js +2 -0
  9. package/dist/chunk-TS3IWH5U.js +6097 -0
  10. package/dist/chunk-TS3IWH5U.js.map +1 -0
  11. package/dist/chunk-WUYSZAYR.js +8383 -0
  12. package/dist/chunk-WUYSZAYR.js.map +1 -0
  13. package/dist/chunk-XKZSX5BM.js +327 -0
  14. package/dist/chunk-XKZSX5BM.js.map +1 -0
  15. package/dist/chunk-YQFEGFWD.js +89 -0
  16. package/dist/chunk-YQFEGFWD.js.map +1 -0
  17. package/dist/discovery-D23RV7FY.js +108 -0
  18. package/dist/discovery-D23RV7FY.js.map +1 -0
  19. package/dist/index.js +2986 -1514
  20. package/dist/index.js.map +1 -1
  21. package/dist/project-identity-worker.js +4 -2
  22. package/dist/project-identity-worker.js.map +1 -1
  23. package/dist/scan-refresh-worker.js +129 -138
  24. package/dist/scan-refresh-worker.js.map +1 -1
  25. package/dist/search-index-worker.js +36 -12
  26. package/dist/search-index-worker.js.map +1 -1
  27. package/dist/session-detail-worker.js +79 -0
  28. package/dist/session-detail-worker.js.map +1 -0
  29. package/dist/smart-tag-worker.js +8 -5
  30. package/dist/smart-tag-worker.js.map +1 -1
  31. package/dist/web/assets/CustomTimeWindowDialog-C9XTZRm0.js +1 -0
  32. package/dist/web/assets/InteractiveReceipt-Sca1smpv.js +1 -0
  33. package/dist/web/assets/OverviewScreen-Vq6BQR9_.js +1 -0
  34. package/dist/web/assets/{PrismHighlighter-BZkkX0AU.js → PrismHighlighter-LWITDffT.js} +2 -2
  35. package/dist/web/assets/Projects-CwicV3Dk.js +1 -0
  36. package/dist/web/assets/SearchResultsPanel-DCO0Ak0c.js +1 -0
  37. package/dist/web/assets/SessionDetail-mdmTQgo1.js +53 -0
  38. package/dist/web/assets/api-CXVT9XcZ.js +1 -0
  39. package/dist/web/assets/contract-BS78VBCV.js +2 -0
  40. package/dist/web/assets/{index-3UfOiTBO.css → index-C5cyw58A.css} +1 -1
  41. package/dist/web/assets/index-H2cT-6c6.js +1423 -0
  42. package/dist/web/assets/{session-indexes-BPhf1X2P.js → session-indexes-yyyWpKLf.js} +2 -2
  43. package/dist/web/assets/utils-C7BqyxxV.js +1 -0
  44. package/dist/web/index.html +7 -11
  45. package/package.json +4 -10
  46. package/dist/chunk-PSHZZITB.js +0 -17307
  47. package/dist/chunk-PSHZZITB.js.map +0 -1
  48. package/dist/chunk-WAKW5OPS.js +0 -241
  49. package/dist/chunk-WAKW5OPS.js.map +0 -1
  50. package/dist/dist-RHDY2EZX.js +0 -173
  51. package/dist/web/assets/ErrorBoundary-DIwwrdlw.js +0 -1
  52. package/dist/web/assets/InteractiveReceipt-DmNBDVms.js +0 -1
  53. package/dist/web/assets/OverviewScreen-B5JekBLC.js +0 -1
  54. package/dist/web/assets/Projects-Bj6ma2k2.js +0 -1
  55. package/dist/web/assets/SearchFilterBar-B9VrUbym.js +0 -1
  56. package/dist/web/assets/SearchResultsPanel-C1cuuOKq.js +0 -1
  57. package/dist/web/assets/SessionDetail-Dc2CQ3hH.js +0 -54
  58. package/dist/web/assets/SmartTagChips-ux6idUGJ.js +0 -1
  59. package/dist/web/assets/agents-BkRP_ww3.js +0 -1
  60. package/dist/web/assets/code-metrics-UYFsCC7E.js +0 -1
  61. package/dist/web/assets/contract-DXvltqJG.js +0 -1
  62. package/dist/web/assets/index-DBMiEd61.js +0 -1410
  63. package/dist/web/assets/panel-CLnL4kMN.js +0 -1
  64. package/dist/web/assets/session-title-DdtlxtlR.js +0 -1
  65. package/dist/web/assets/utils-BKqufGdv.js +0 -1
  66. /package/dist/{dist-RHDY2EZX.js.map → chunk-QH2HOXJH.js.map} +0 -0
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-WAKW5OPS.js";
2
+ import "./chunk-FCYCBGEL.js";
3
+ import "./chunk-PAP2Q3WV.js";
3
4
  import {
4
5
  computeIdentityProjection
5
- } from "./chunk-PSHZZITB.js";
6
+ } from "./chunk-XKZSX5BM.js";
7
+ import "./chunk-NBJJGH5P.js";
6
8
 
7
9
  // src/project-identity-worker.ts
8
10
  import { parentPort } from "worker_threads";
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/project-identity-worker.ts"],"sourcesContent":["import \"./diagnostics-bridge.js\";\nimport { parentPort } from \"node:worker_threads\";\nimport { computeIdentityProjection, type ProjectIdentityProjection } from \"@codesesh/core\";\n\nexport interface ProjectIdentityWorkerRequest {\n type: \"resolve\";\n requestId: number;\n cwd: string;\n}\n\nexport type ProjectIdentityWorkerMessage =\n | {\n type: \"resolved\";\n requestId: number;\n projection: ProjectIdentityProjection;\n }\n | {\n type: \"failed\";\n requestId: number;\n error: string;\n };\n\nfunction resolveIdentity(request: ProjectIdentityWorkerRequest): void {\n try {\n parentPort?.postMessage({\n type: \"resolved\",\n requestId: request.requestId,\n projection: computeIdentityProjection(request.cwd),\n } satisfies ProjectIdentityWorkerMessage);\n } catch (error) {\n parentPort?.postMessage({\n type: \"failed\",\n requestId: request.requestId,\n error: error instanceof Error ? error.message : String(error),\n } satisfies ProjectIdentityWorkerMessage);\n }\n}\n\nparentPort?.on(\"message\", (message: ProjectIdentityWorkerRequest) => {\n if (message.type === \"resolve\") resolveIdentity(message);\n});\n"],"mappings":";;;;;;;AACA,SAAS,kBAAkB;AAqB3B,SAAS,gBAAgB,SAA6C;AACpE,MAAI;AACF,gBAAY,YAAY;AAAA,MACtB,MAAM;AAAA,MACN,WAAW,QAAQ;AAAA,MACnB,YAAY,0BAA0B,QAAQ,GAAG;AAAA,IACnD,CAAwC;AAAA,EAC1C,SAAS,OAAO;AACd,gBAAY,YAAY;AAAA,MACtB,MAAM;AAAA,MACN,WAAW,QAAQ;AAAA,MACnB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D,CAAwC;AAAA,EAC1C;AACF;AAEA,YAAY,GAAG,WAAW,CAAC,YAA0C;AACnE,MAAI,QAAQ,SAAS,UAAW,iBAAgB,OAAO;AACzD,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/project-identity-worker.ts"],"sourcesContent":["import \"./diagnostics-bridge.js\";\nimport { parentPort } from \"node:worker_threads\";\nimport {\n computeIdentityProjection,\n type ProjectIdentityProjection,\n} from \"@codesesh/core/runtime/projects\";\n\nexport interface ProjectIdentityWorkerRequest {\n type: \"resolve\";\n requestId: number;\n cwd: string;\n}\n\nexport type ProjectIdentityWorkerMessage =\n | {\n type: \"resolved\";\n requestId: number;\n projection: ProjectIdentityProjection;\n }\n | {\n type: \"failed\";\n requestId: number;\n error: string;\n };\n\nfunction resolveIdentity(request: ProjectIdentityWorkerRequest): void {\n try {\n parentPort?.postMessage({\n type: \"resolved\",\n requestId: request.requestId,\n projection: computeIdentityProjection(request.cwd),\n } satisfies ProjectIdentityWorkerMessage);\n } catch (error) {\n parentPort?.postMessage({\n type: \"failed\",\n requestId: request.requestId,\n error: error instanceof Error ? error.message : String(error),\n } satisfies ProjectIdentityWorkerMessage);\n }\n}\n\nparentPort?.on(\"message\", (message: ProjectIdentityWorkerRequest) => {\n if (message.type === \"resolve\") resolveIdentity(message);\n});\n"],"mappings":";;;;;;;;;AACA,SAAS,kBAAkB;AAwB3B,SAAS,gBAAgB,SAA6C;AACpE,MAAI;AACF,gBAAY,YAAY;AAAA,MACtB,MAAM;AAAA,MACN,WAAW,QAAQ;AAAA,MACnB,YAAY,0BAA0B,QAAQ,GAAG;AAAA,IACnD,CAAwC;AAAA,EAC1C,SAAS,OAAO;AACd,gBAAY,YAAY;AAAA,MACtB,MAAM;AAAA,MACN,WAAW,QAAQ;AAAA,MACnB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D,CAAwC;AAAA,EAC1C;AACF;AAEA,YAAY,GAAG,WAAW,CAAC,YAA0C;AACnE,MAAI,QAAQ,SAAS,UAAW,iBAAgB,OAAO;AACzD,CAAC;","names":[]}
@@ -2,26 +2,33 @@
2
2
  import {
3
3
  AgentUnavailableDuringScanError
4
4
  } from "./chunk-RF3EEWPH.js";
5
+ import {
6
+ acknowledgeWorkerLogDrain
7
+ } from "./chunk-YQFEGFWD.js";
8
+ import "./chunk-QH2HOXJH.js";
5
9
  import {
6
10
  appLogger
7
- } from "./chunk-WAKW5OPS.js";
11
+ } from "./chunk-PAP2Q3WV.js";
8
12
  import {
9
- FileSystemSessionSource,
10
- SMART_TAG_CLASSIFIER_REVISION,
11
13
  attachMissingProjectIdentities,
12
14
  buildAgentCacheMeta,
13
- computeSessionDiff,
14
- createRegisteredAgents,
15
+ buildSessionPersistenceDiff,
15
16
  ensureSessionTagsSync,
16
- sessionSignature,
17
- sortSessions,
18
- synchronizePricingGeneration,
19
- synchronizeSessionSources
20
- } from "./chunk-PSHZZITB.js";
17
+ executeAgentScanPlan,
18
+ hasStaleSessionTags,
19
+ planAgentScan,
20
+ sortSessions
21
+ } from "./chunk-TS3IWH5U.js";
22
+ import "./chunk-XKZSX5BM.js";
23
+ import {
24
+ createRegisteredAgents
25
+ } from "./chunk-WUYSZAYR.js";
26
+ import {
27
+ synchronizePricingGeneration
28
+ } from "./chunk-NBJJGH5P.js";
21
29
 
22
30
  // src/scan-refresh-worker.ts
23
31
  import { parentPort, workerData } from "worker_threads";
24
- import { isDeepStrictEqual } from "util";
25
32
 
26
33
  // src/monotonic-value-sampler.ts
27
34
  var MonotonicValueSampler = class {
@@ -72,62 +79,66 @@ var MonotonicValueSampler = class {
72
79
  }
73
80
  };
74
81
 
75
- // src/scan-refresh-operation.ts
76
- function synchronizesSessionSources(operation) {
77
- return operation.kind === "source-refresh" || operation.kind === "source-backfill";
82
+ // src/scan-refresh-delta.ts
83
+ import { isDeepStrictEqual } from "util";
84
+ function buildScanRefreshDelta(input) {
85
+ const meta = {};
86
+ const removedMetaIds = [];
87
+ for (const [id, value] of Object.entries(input.nextMeta)) {
88
+ if (!isDeepStrictEqual(input.previousMeta[id], value)) meta[id] = value;
89
+ }
90
+ for (const id of Object.keys(input.previousMeta)) {
91
+ if (!Object.hasOwn(input.nextMeta, id)) removedMetaIds.push(id);
92
+ }
93
+ const diff = buildSessionPersistenceDiff(input.previousSessions, input.sessions, {
94
+ candidateChangedIds: [...input.changedIds ?? [], ...Object.keys(meta), ...removedMetaIds],
95
+ completeness: input.completeness,
96
+ explicitRemovedSessionIds: input.explicitRemovedSessionIds
97
+ });
98
+ return {
99
+ changes: diff.changedSessions,
100
+ removedSessionIds: diff.removedSessionIds,
101
+ meta,
102
+ removedMetaIds
103
+ };
78
104
  }
105
+
106
+ // src/scan-refresh-operation.ts
79
107
  function isBackfillOperation(operation) {
80
- return operation.kind === "full-backfill" || operation.kind === "source-backfill";
108
+ return operation.kind === "backfill";
81
109
  }
82
110
  function usesDurableCheckpoints(operation) {
83
111
  return "checkpoint" in operation && operation.checkpoint === "durable";
84
112
  }
85
-
86
- // src/scan-refresh-worker.ts
87
- function computeCacheMetaDiff(previous, next) {
88
- const changes = {};
89
- const removedIds = [];
90
- for (const [id, meta] of Object.entries(next)) {
91
- if (!isDeepStrictEqual(previous[id], meta)) changes[id] = meta;
92
- }
93
- for (const id of Object.keys(previous)) {
94
- if (!Object.hasOwn(next, id)) removedIds.push(id);
113
+ function scanIntentForOperation(operation) {
114
+ switch (operation.kind) {
115
+ case "full-scan":
116
+ return "reload";
117
+ case "source-refresh":
118
+ return "refresh";
119
+ case "recompute-derived":
120
+ return "recompute-derived";
121
+ case "backfill":
122
+ return "backfill";
95
123
  }
96
- return { changes, removedIds };
97
- }
98
- function hasStaleSmartTags(session) {
99
- const sourceUpdatedAt = session.time_updated ?? session.time_created;
100
- return !Array.isArray(session.smart_tags) || session.smart_tags_source_updated_at !== sourceUpdatedAt || session.smart_tags_classifier_revision !== SMART_TAG_CLASSIFIER_REVISION;
101
124
  }
125
+
126
+ // src/scan-refresh-worker.ts
102
127
  function selectBackfillSessions(sessions, changedIds, cursor) {
103
128
  const orderedSessions = sortSessions(sessions);
104
- const cursorIndex = cursor ? orderedSessions.findIndex((session) => session.id === cursor) : -1;
129
+ const cursorIndex = cursor ? orderedSessions.findIndex((session) => session.reference.sessionId === cursor) : -1;
105
130
  const finalizeSessionIds = /* @__PURE__ */ new Set();
106
131
  const startIndex = cursorIndex >= 0 ? cursorIndex + 1 : 0;
107
132
  for (let index = startIndex; index < orderedSessions.length; index += 1) {
108
- finalizeSessionIds.add(orderedSessions[index].id);
133
+ finalizeSessionIds.add(orderedSessions[index].reference.sessionId);
109
134
  }
110
135
  for (const changedId of changedIds) finalizeSessionIds.add(changedId);
111
136
  for (let index = 0; index <= cursorIndex; index += 1) {
112
137
  const session = orderedSessions[index];
113
- if (hasStaleSmartTags(session)) finalizeSessionIds.add(session.id);
138
+ if (hasStaleSessionTags(session)) finalizeSessionIds.add(session.reference.sessionId);
114
139
  }
115
140
  return { orderedSessions, finalizeSessionIds, cursorIndex };
116
141
  }
117
- function inheritSmartTags(sessions, previousSessions) {
118
- const previousById = new Map(previousSessions.map((session) => [session.id, session]));
119
- return sessions.map((session) => {
120
- if (Array.isArray(session.smart_tags)) return session;
121
- const previous = previousById.get(session.id);
122
- if (!previous || !Array.isArray(previous.smart_tags)) return session;
123
- return {
124
- ...session,
125
- smart_tags: previous.smart_tags,
126
- smart_tags_source_updated_at: previous.smart_tags_source_updated_at,
127
- smart_tags_classifier_revision: previous.smart_tags_classifier_revision
128
- };
129
- });
130
- }
131
142
  var TAG_SETTLE_MS = 6e4;
132
143
  var TAG_CHECKPOINT_SIZE = 32;
133
144
  var PROGRESS_INTERVAL_MS = 100;
@@ -164,7 +175,7 @@ function finalizeSessions(agent, sessions, onProgress, onCheckpoint, finalizeSes
164
175
  const ordered = sortSessions(attachMissingProjectIdentities(sessions));
165
176
  const now = Date.now();
166
177
  const settled = ordered.filter(
167
- (session) => (!finalizeSessionIds || finalizeSessionIds.has(session.id)) && isSettled(session, now)
178
+ (session) => (!finalizeSessionIds || finalizeSessionIds.has(session.reference.sessionId)) && isSettled(session, now)
168
179
  );
169
180
  if (settled.length === 0) return ordered;
170
181
  let lastReportedAt = -Infinity;
@@ -180,7 +191,9 @@ function finalizeSessions(agent, sessions, onProgress, onCheckpoint, finalizeSes
180
191
  });
181
192
  };
182
193
  reportProgress(0, settled.length);
183
- const sortIndexById = new Map(ordered.map((session, index) => [session.id, index]));
194
+ const sortIndexById = new Map(
195
+ ordered.map((session, index) => [session.reference.sessionId, index])
196
+ );
184
197
  const taggedById = /* @__PURE__ */ new Map();
185
198
  for (let start = 0; start < settled.length; start += TAG_CHECKPOINT_SIZE) {
186
199
  const batch = settled.slice(start, start + TAG_CHECKPOINT_SIZE);
@@ -189,17 +202,20 @@ function finalizeSessions(agent, sessions, onProgress, onCheckpoint, finalizeSes
189
202
  });
190
203
  if (taggedResult.timing) onTiming?.(taggedResult.timing);
191
204
  const taggedBatch = taggedResult.sessions;
192
- for (const session of taggedBatch) taggedById.set(session.id, session);
205
+ for (const session of taggedBatch) taggedById.set(session.reference.sessionId, session);
193
206
  onCheckpoint?.({
194
207
  stage: "finalizing",
195
208
  changes: taggedBatch.map((session) => ({
196
209
  session,
197
- sortIndex: sortIndexById.get(session.id) ?? 0
210
+ sortIndex: sortIndexById.get(session.reference.sessionId) ?? 0
198
211
  })),
199
- meta: buildAgentCacheMeta(agent, new Set(taggedBatch.map((session) => session.id)))
212
+ meta: buildAgentCacheMeta(
213
+ agent,
214
+ new Set(taggedBatch.map((session) => session.reference.sessionId))
215
+ )
200
216
  });
201
217
  }
202
- return ordered.map((session) => taggedById.get(session.id) ?? session);
218
+ return ordered.map((session) => taggedById.get(session.reference.sessionId) ?? session);
203
219
  }
204
220
  var workerBaseline = null;
205
221
  function baselineFor(data) {
@@ -233,7 +249,7 @@ function baselineFor(data) {
233
249
  if (workerBaseline.staged) {
234
250
  throw new Error(`Worker result ${workerBaseline.staged.requestId} is awaiting commit`);
235
251
  }
236
- workerBaseline.agent.setSessionMetaMap(new Map(Object.entries(workerBaseline.meta)));
252
+ workerBaseline.agent.restoreSessionCacheMeta(workerBaseline.meta);
237
253
  return workerBaseline;
238
254
  }
239
255
  async function run(data, progressEmitter) {
@@ -243,15 +259,14 @@ async function run(data, progressEmitter) {
243
259
  const previousSessions = baseline.sessions;
244
260
  const previousMeta = baseline.meta;
245
261
  const operation = data.operation;
246
- const sourceSynchronization = synchronizesSessionSources(operation);
247
262
  const backfill = isBackfillOperation(operation);
263
+ const scanPlan = planAgentScan(agent.sessionSourceAccess, scanIntentForOperation(operation));
248
264
  const durableCheckpoints = usesDurableCheckpoints(operation);
249
265
  const backfillCursor = backfill ? operation.cursor : void 0;
250
266
  appLogger.debug("scan.refresh_worker.started", {
251
267
  agent: data.agentName,
252
268
  operation: operation.kind,
253
269
  backfill_cursor: backfillCursor ?? void 0,
254
- changed_ids: operation.kind === "incremental-scan" ? operation.changedIds.length : 0,
255
270
  previous_sessions: previousSessions.length
256
271
  });
257
272
  const reportProgress = (progress) => {
@@ -264,74 +279,33 @@ async function run(data, progressEmitter) {
264
279
  });
265
280
  throw new AgentUnavailableDuringScanError(data.agentName);
266
281
  }
267
- let sessions;
268
- let changedIds;
269
- let sourceFailures = [];
270
- let explicitRemovedSessionIds = [];
271
- let finalizeSessionIds;
282
+ if (scanPlan.kind === "check-for-changes") {
283
+ throw new Error(`Change checks must run before dispatching Agent ${agent.name} to the worker`);
284
+ }
285
+ const execution = executeAgentScanPlan(
286
+ agent,
287
+ scanPlan,
288
+ { sessions: previousSessions, meta: previousMeta },
289
+ { ...data.scanOptions, onProgress: reportProgress }
290
+ );
291
+ let sessions = execution.sessions;
292
+ const changedIds = execution.changedSessionIds;
293
+ const sourceFailures = execution.sourceFailures;
294
+ const explicitRemovedSessionIds = execution.explicitRemovedSessionIds;
295
+ let finalizeSessionIds = execution.finalizeSessionIds === void 0 ? void 0 : new Set(execution.finalizeSessionIds);
272
296
  let backfillOrder;
273
297
  let backfillCursorIndex = -1;
274
- let sourceSynchronizationDetails;
275
- if (operation.kind === "recompute-derived") {
276
- sessions = previousSessions;
277
- } else if (sourceSynchronization) {
278
- if (!(agent instanceof FileSystemSessionSource)) {
279
- throw new Error(`Agent ${agent.name} does not support Session Source synchronization`);
280
- }
281
- const result = synchronizeSessionSources(
282
- agent,
283
- { sessions: previousSessions, meta: previousMeta },
284
- {
285
- kind: "refresh",
286
- scanOptions: { ...data.scanOptions, onProgress: reportProgress }
287
- }
288
- );
289
- sessions = result.sessions;
290
- changedIds = result.changedSessionIds;
291
- finalizeSessionIds = new Set(result.finalizeSessionIds);
292
- sourceSynchronizationDetails = {
293
- sourceCount: result.sourceCount,
294
- removedCount: result.removedSourceCount
295
- };
296
- sourceFailures = result.sourceFailures;
297
- explicitRemovedSessionIds = result.explicitRemovedSessionIds;
298
- } else if (operation.kind === "incremental-scan") {
299
- changedIds = operation.changedIds;
300
- sessions = inheritSmartTags(
301
- await Promise.resolve(
302
- agent.incrementalScan(previousSessions, operation.changedIds, void 0, {
303
- ...data.scanOptions,
304
- onProgress: reportProgress
305
- })
306
- ),
307
- previousSessions
308
- );
309
- } else if (agent instanceof FileSystemSessionSource) {
310
- const result = synchronizeSessionSources(
311
- agent,
312
- { sessions: previousSessions, meta: previousMeta },
313
- {
314
- kind: "reload",
315
- scanOptions: { ...data.scanOptions, onProgress: reportProgress }
316
- }
317
- );
318
- sessions = result.sessions;
319
- finalizeSessionIds = new Set(result.finalizeSessionIds);
320
- sourceFailures = result.sourceFailures;
321
- explicitRemovedSessionIds = result.explicitRemovedSessionIds;
322
- } else {
323
- sessions = inheritSmartTags(
324
- await Promise.resolve(
325
- agent.scan({
326
- ...data.scanOptions,
327
- onProgress: reportProgress
328
- })
329
- ),
330
- previousSessions
331
- );
332
- }
298
+ const sourceSynchronizationDetails = execution.sourceSynchronization ? {
299
+ sourceCount: execution.sourceSynchronization.sourceCount,
300
+ removedCount: execution.sourceSynchronization.removedSourceCount,
301
+ enumerationMs: execution.sourceSynchronization.timing.enumerationMs,
302
+ diffMs: execution.sourceSynchronization.timing.diffMs,
303
+ parseMs: execution.sourceSynchronization.timing.parseMs,
304
+ changedCount: execution.sourceSynchronization.timing.changedSourceCount,
305
+ processedCount: execution.sourceSynchronization.timing.processedSourceCount
306
+ } : void 0;
333
307
  sessions = attachMissingProjectIdentities(sessions);
334
- const completeness = data.scanOptions.from == null && data.scanOptions.to == null && sourceFailures.length === 0 ? "complete" : "partial";
308
+ const completeness = execution.completeness;
335
309
  if (durableCheckpoints) {
336
310
  const ordered = sortSessions(sessions);
337
311
  parentPort?.postMessage({
@@ -341,7 +315,10 @@ async function run(data, progressEmitter) {
341
315
  checkpoint: {
342
316
  stage: "scanned",
343
317
  sessions: ordered,
344
- meta: buildAgentCacheMeta(agent, new Set(ordered.map((session) => session.id))),
318
+ meta: buildAgentCacheMeta(
319
+ agent,
320
+ new Set(ordered.map((session) => session.reference.sessionId))
321
+ ),
345
322
  completeness
346
323
  }
347
324
  });
@@ -363,12 +340,17 @@ async function run(data, progressEmitter) {
363
340
  changed_ids: changedIds?.length ?? 0,
364
341
  source_count: sourceSynchronizationDetails?.sourceCount,
365
342
  removed_count: sourceSynchronizationDetails?.removedCount,
343
+ source_enumeration_ms: roundMilliseconds(sourceSynchronizationDetails?.enumerationMs ?? 0),
344
+ source_diff_ms: roundMilliseconds(sourceSynchronizationDetails?.diffMs ?? 0),
345
+ source_parse_ms: roundMilliseconds(sourceSynchronizationDetails?.parseMs ?? 0),
346
+ changed_sources: sourceSynchronizationDetails?.changedCount,
347
+ processed_sources: sourceSynchronizationDetails?.processedCount,
366
348
  failed_sources: sourceFailures.length,
367
349
  duration_ms: Math.round(scanDuration)
368
350
  });
369
351
  const finalizeStartedAt = performance.now();
370
352
  const finalizationTiming = createSessionFinalizationTiming();
371
- const backfillPositionById = backfillOrder ? new Map(backfillOrder.map((session, index) => [session.id, index])) : void 0;
353
+ const backfillPositionById = backfillOrder ? new Map(backfillOrder.map((session, index) => [session.reference.sessionId, index])) : void 0;
372
354
  sessions = finalizeSessions(
373
355
  agent,
374
356
  sessions,
@@ -378,14 +360,14 @@ async function run(data, progressEmitter) {
378
360
  if (checkpoint.stage === "finalizing" && backfillOrder && backfillPositionById) {
379
361
  let nextCursorIndex = backfillCursorIndex;
380
362
  for (const { session } of checkpoint.changes) {
381
- const index = backfillPositionById.get(session.id);
363
+ const index = backfillPositionById.get(session.reference.sessionId);
382
364
  if (index != null && index > nextCursorIndex) nextCursorIndex = index;
383
365
  }
384
366
  if (nextCursorIndex > backfillCursorIndex) {
385
367
  backfillCursorIndex = nextCursorIndex;
386
368
  nextCheckpoint = {
387
369
  ...checkpoint,
388
- backfillCursor: backfillOrder[nextCursorIndex]?.id
370
+ backfillCursor: backfillOrder[nextCursorIndex]?.reference.sessionId
389
371
  };
390
372
  }
391
373
  }
@@ -422,7 +404,7 @@ async function run(data, progressEmitter) {
422
404
  appLogger.debug("scan.refresh_worker.finalized", {
423
405
  agent: data.agentName,
424
406
  operation: operation.kind,
425
- backfill_cursor: backfillOrder?.[backfillCursorIndex]?.id,
407
+ backfill_cursor: backfillOrder?.[backfillCursorIndex]?.reference.sessionId,
426
408
  sessions: sessions.length,
427
409
  finalized_sessions: finalizationTiming.sessions,
428
410
  batches: finalizationTiming.batches,
@@ -443,14 +425,19 @@ async function run(data, progressEmitter) {
443
425
  duration_ms: roundMilliseconds(finalizationDuration),
444
426
  total_duration_ms: Math.round(performance.now() - startedAt)
445
427
  });
446
- const nextMeta = buildAgentCacheMeta(agent, new Set(sessions.map((session) => session.id)));
447
- const metaDiff = computeCacheMetaDiff(previousMeta, nextMeta);
448
- const diff = computeSessionDiff(
428
+ const nextMeta = buildAgentCacheMeta(
429
+ agent,
430
+ new Set(sessions.map((session) => session.reference.sessionId))
431
+ );
432
+ const delta = buildScanRefreshDelta({
449
433
  previousSessions,
450
434
  sessions,
451
- [...changedIds ?? [], ...Object.keys(metaDiff.changes), ...metaDiff.removedIds],
452
- sessionSignature
453
- );
435
+ previousMeta,
436
+ nextMeta,
437
+ changedIds,
438
+ completeness,
439
+ explicitRemovedSessionIds
440
+ });
454
441
  baseline.staged = {
455
442
  requestId: data.requestId,
456
443
  generation: baseline.generation,
@@ -462,10 +449,7 @@ async function run(data, progressEmitter) {
462
449
  type: "done",
463
450
  requestId: data.requestId,
464
451
  generation: baseline.generation,
465
- changes: diff.changes,
466
- removedSessionIds: diff.removedSessionIds,
467
- meta: metaDiff.changes,
468
- removedMetaIds: metaDiff.removedIds,
452
+ ...delta,
469
453
  sourceFailures,
470
454
  completeness,
471
455
  explicitRemovedSessionIds,
@@ -532,7 +516,12 @@ function handleCommit(data) {
532
516
  }
533
517
  }
534
518
  function enqueueRequest(data) {
535
- requestTail = requestTail.then(() => data.type === "commit" ? handleCommit(data) : handleRequest(data)).catch((error) => {
519
+ requestTail = requestTail.then(
520
+ () => appLogger.restoreContext(
521
+ data.logContext ?? {},
522
+ () => data.type === "commit" ? handleCommit(data) : handleRequest(data)
523
+ )
524
+ ).catch((error) => {
536
525
  appLogger.error("scan.refresh_worker.request_error", {
537
526
  request_id: data.requestId,
538
527
  request_type: data.type,
@@ -544,7 +533,9 @@ var initialRequest = workerData;
544
533
  if (initialRequest?.type === "run" && typeof initialRequest.requestId === "number" && typeof initialRequest.agentName === "string" && typeof initialRequest.pricingGenerationId === "number" && initialRequest.operation != null && Array.isArray(initialRequest.previousSessions) && initialRequest.meta != null) {
545
534
  enqueueRequest(initialRequest);
546
535
  }
547
- parentPort?.on("message", (message) => {
536
+ var workerPort = parentPort;
537
+ workerPort?.on("message", (message) => {
538
+ if (acknowledgeWorkerLogDrain(workerPort, message, requestTail)) return;
548
539
  enqueueRequest(message);
549
540
  });
550
541
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/scan-refresh-worker.ts","../src/monotonic-value-sampler.ts","../src/scan-refresh-operation.ts"],"sourcesContent":["import \"./diagnostics-bridge.js\";\nimport { parentPort, workerData } from \"node:worker_threads\";\nimport { isDeepStrictEqual } from \"node:util\";\nimport {\n attachMissingProjectIdentities,\n buildAgentCacheMeta,\n computeSessionDiff,\n createRegisteredAgents,\n ensureSessionTagsSync,\n FileSystemSessionSource,\n sessionSignature,\n SMART_TAG_CLASSIFIER_REVISION,\n sortSessions,\n synchronizePricingGeneration,\n synchronizeSessionSources,\n type AgentScanProgress,\n type BaseAgent,\n type ScanOptions,\n type SessionCacheMeta,\n type SessionHead,\n type PersistedSessionHeadChange,\n type SessionSourceFailure,\n type SessionSnapshotCompleteness,\n type SessionTagTiming,\n} from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\nimport { MonotonicValueSampler } from \"./monotonic-value-sampler.js\";\nimport {\n AgentUnavailableDuringScanError,\n type ScanRefreshWorkerErrorCode,\n} from \"./scan-refresh-error.js\";\nimport {\n isBackfillOperation,\n synchronizesSessionSources,\n usesDurableCheckpoints,\n type ScanRefreshOperation,\n} from \"./scan-refresh-operation.js\";\n\nexport type ScanRefreshWorkerMessage =\n | {\n type: \"progress\";\n requestId: number;\n generation: number;\n progress: AgentScanProgress;\n }\n | {\n type: \"checkpoint\";\n requestId: number;\n generation: number;\n checkpoint: ScanRefreshWorkerCheckpoint;\n }\n | {\n type: \"done\";\n requestId: number;\n generation: number;\n changes: PersistedSessionHeadChange[];\n removedSessionIds: string[];\n meta: Record<string, SessionCacheMeta>;\n removedMetaIds: string[];\n sourceFailures: SessionSourceFailure[];\n completeness: SessionSnapshotCompleteness;\n explicitRemovedSessionIds: string[];\n durationMs: number;\n }\n | {\n type: \"error\";\n requestId: number;\n generation: number;\n error: string;\n errorCode?: ScanRefreshWorkerErrorCode;\n durationMs: number;\n };\n\nexport type ScanRefreshWorkerCheckpoint =\n | {\n stage: \"scanned\";\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n completeness: SessionSnapshotCompleteness;\n }\n | {\n stage: \"finalizing\";\n changes: PersistedSessionHeadChange[];\n meta: Record<string, SessionCacheMeta>;\n backfillCursor?: string;\n };\n\nexport interface ScanRefreshWorkerRunRequest {\n type: \"run\";\n requestId: number;\n agentName: string;\n generation: number;\n pricingGenerationId: number;\n previousSessions?: SessionHead[];\n operation: ScanRefreshOperation;\n scanOptions: Pick<ScanOptions, \"from\" | \"to\" | \"fast\">;\n meta?: Record<string, SessionCacheMeta>;\n}\n\nexport interface ScanRefreshWorkerCommitRequest {\n type: \"commit\";\n requestId: number;\n generation: number;\n}\n\nexport type ScanRefreshWorkerRequest = ScanRefreshWorkerRunRequest | ScanRefreshWorkerCommitRequest;\n\ninterface StagedWorkerBaseline {\n requestId: number;\n generation: number;\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n}\n\ninterface WorkerBaseline {\n agentName: string;\n agent: BaseAgent;\n generation: number;\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n staged: StagedWorkerBaseline | null;\n}\n\ninterface CacheMetaDiff {\n changes: Record<string, SessionCacheMeta>;\n removedIds: string[];\n}\n\nfunction computeCacheMetaDiff(\n previous: Record<string, SessionCacheMeta>,\n next: Record<string, SessionCacheMeta>,\n): CacheMetaDiff {\n const changes: Record<string, SessionCacheMeta> = {};\n const removedIds: string[] = [];\n for (const [id, meta] of Object.entries(next)) {\n if (!isDeepStrictEqual(previous[id], meta)) changes[id] = meta;\n }\n for (const id of Object.keys(previous)) {\n if (!Object.hasOwn(next, id)) removedIds.push(id);\n }\n return { changes, removedIds };\n}\n\nfunction hasStaleSmartTags(session: SessionHead): boolean {\n const sourceUpdatedAt = session.time_updated ?? session.time_created;\n return (\n !Array.isArray(session.smart_tags) ||\n session.smart_tags_source_updated_at !== sourceUpdatedAt ||\n session.smart_tags_classifier_revision !== SMART_TAG_CLASSIFIER_REVISION\n );\n}\n\ninterface BackfillSelection {\n orderedSessions: SessionHead[];\n finalizeSessionIds: ReadonlySet<string>;\n cursorIndex: number;\n}\n\nfunction selectBackfillSessions(\n sessions: SessionHead[],\n changedIds: string[],\n cursor: string | null | undefined,\n): BackfillSelection {\n const orderedSessions = sortSessions(sessions);\n const cursorIndex = cursor ? orderedSessions.findIndex((session) => session.id === cursor) : -1;\n const finalizeSessionIds = new Set<string>();\n const startIndex = cursorIndex >= 0 ? cursorIndex + 1 : 0;\n\n for (let index = startIndex; index < orderedSessions.length; index += 1) {\n finalizeSessionIds.add(orderedSessions[index]!.id);\n }\n\n for (const changedId of changedIds) finalizeSessionIds.add(changedId);\n\n // A hot session before the cursor remains stale until it settles. Keep it in\n // the next pass so it is not permanently skipped when it becomes idle.\n for (let index = 0; index <= cursorIndex; index += 1) {\n const session = orderedSessions[index]!;\n if (hasStaleSmartTags(session)) finalizeSessionIds.add(session.id);\n }\n\n return { orderedSessions, finalizeSessionIds, cursorIndex };\n}\n\n/**\n * scan() rebuilds heads from the source without smart tags, which would force\n * a full reclassification pass (one getSessionData() per session). Carry the\n * previous tags over and let the staleness check in ensureSessionTagsSync —\n * smart_tags_source_updated_at vs time_updated — decide what to recompute.\n */\nfunction inheritSmartTags(sessions: SessionHead[], previousSessions: SessionHead[]): SessionHead[] {\n const previousById = new Map(previousSessions.map((session) => [session.id, session]));\n return sessions.map((session) => {\n if (Array.isArray(session.smart_tags)) return session;\n const previous = previousById.get(session.id);\n if (!previous || !Array.isArray(previous.smart_tags)) return session;\n return {\n ...session,\n smart_tags: previous.smart_tags,\n smart_tags_source_updated_at: previous.smart_tags_source_updated_at,\n smart_tags_classifier_revision: previous.smart_tags_classifier_revision,\n };\n });\n}\n\n/**\n * A session still receiving writes will be stale again within seconds, so\n * recomputing its tags every refresh cycle is wasted work — wait for it to\n * settle before paying the getSessionData() parse cost.\n */\nconst TAG_SETTLE_MS = 60_000;\nconst TAG_CHECKPOINT_SIZE = 32;\nconst PROGRESS_INTERVAL_MS = 100;\n\ninterface SessionFinalizationTiming extends SessionTagTiming {\n batches: number;\n}\n\nfunction createSessionFinalizationTiming(): SessionFinalizationTiming {\n return {\n batches: 0,\n sessions: 0,\n cacheHits: 0,\n staleSessions: 0,\n failedSessions: 0,\n getSessionDataCalls: 0,\n getSessionDataMs: 0,\n classifySessionTagsCalls: 0,\n classifySessionTagsMs: 0,\n };\n}\n\nfunction addSessionTagTiming(target: SessionFinalizationTiming, source: SessionTagTiming): void {\n target.sessions += source.sessions;\n target.cacheHits += source.cacheHits;\n target.staleSessions += source.staleSessions;\n target.failedSessions += source.failedSessions;\n target.getSessionDataCalls += source.getSessionDataCalls;\n target.getSessionDataMs += source.getSessionDataMs;\n target.classifySessionTagsCalls += source.classifySessionTagsCalls;\n target.classifySessionTagsMs += source.classifySessionTagsMs;\n}\n\nfunction roundMilliseconds(value: number): number {\n return Math.round(value * 100) / 100;\n}\n\nfunction isSettled(session: SessionHead, now: number): boolean {\n return now - (session.time_updated ?? session.time_created) >= TAG_SETTLE_MS;\n}\n\n/**\n * Runs identity resolution (spawns git) and stale smart-tag reclassification\n * on the worker thread, off the server's main event loop.\n */\nexport function finalizeSessions(\n agent: BaseAgent,\n sessions: SessionHead[],\n onProgress?: (progress: AgentScanProgress) => void,\n onCheckpoint?: (checkpoint: ScanRefreshWorkerCheckpoint) => void,\n finalizeSessionIds?: ReadonlySet<string>,\n onTiming?: (timing: SessionTagTiming) => void,\n): SessionHead[] {\n const ordered = sortSessions(attachMissingProjectIdentities(sessions));\n\n const now = Date.now();\n const settled = ordered.filter(\n (session) =>\n (!finalizeSessionIds || finalizeSessionIds.has(session.id)) && isSettled(session, now),\n );\n if (settled.length === 0) return ordered;\n\n let lastReportedAt = -Infinity;\n const reportProgress = (processed: number, total: number): void => {\n const now = performance.now();\n if (processed !== 0 && processed !== total && now - lastReportedAt < 100) return;\n lastReportedAt = now;\n onProgress?.({\n phase: \"finalizing\",\n total,\n processed,\n sessions: ordered.length,\n });\n };\n reportProgress(0, settled.length);\n\n const sortIndexById = new Map(ordered.map((session, index) => [session.id, index]));\n const taggedById = new Map<string, SessionHead>();\n for (let start = 0; start < settled.length; start += TAG_CHECKPOINT_SIZE) {\n const batch = settled.slice(start, start + TAG_CHECKPOINT_SIZE);\n const taggedResult = ensureSessionTagsSync(agent, batch, (processed) => {\n reportProgress(start + processed, settled.length);\n });\n if (taggedResult.timing) onTiming?.(taggedResult.timing);\n const taggedBatch = taggedResult.sessions;\n for (const session of taggedBatch) taggedById.set(session.id, session);\n\n onCheckpoint?.({\n stage: \"finalizing\",\n changes: taggedBatch.map((session) => ({\n session,\n sortIndex: sortIndexById.get(session.id) ?? 0,\n })),\n meta: buildAgentCacheMeta(agent, new Set(taggedBatch.map((session) => session.id))),\n });\n }\n return ordered.map((session) => taggedById.get(session.id) ?? session);\n}\n\nlet workerBaseline: WorkerBaseline | null = null;\n\nfunction baselineFor(data: ScanRefreshWorkerRunRequest): WorkerBaseline {\n const generation = data.generation ?? 0;\n const hasSessions = Array.isArray(data.previousSessions);\n const hasMeta = data.meta != null;\n if (hasSessions !== hasMeta)\n throw new Error(\"Worker baseline requires sessions and meta together\");\n\n if (hasSessions && hasMeta) {\n if (workerBaseline) throw new Error(\"Scan refresh worker baseline is already initialized\");\n const agent = createRegisteredAgents().find((item) => item.name === data.agentName);\n if (!agent) throw new Error(`Unknown agent: ${data.agentName}`);\n workerBaseline = {\n agentName: data.agentName,\n agent,\n generation,\n sessions: data.previousSessions!,\n meta: data.meta!,\n staged: null,\n };\n }\n\n if (!workerBaseline) throw new Error(\"Scan refresh worker baseline is not initialized\");\n if (workerBaseline.agentName !== data.agentName) {\n throw new Error(`Worker Agent mismatch: expected ${workerBaseline.agentName}`);\n }\n if (workerBaseline.generation !== generation) {\n throw new Error(\n `Worker generation mismatch: expected ${workerBaseline.generation}, received ${generation}`,\n );\n }\n if (workerBaseline.staged) {\n throw new Error(`Worker result ${workerBaseline.staged.requestId} is awaiting commit`);\n }\n\n workerBaseline.agent.setSessionMetaMap(new Map(Object.entries(workerBaseline.meta)));\n return workerBaseline;\n}\n\nasync function run(\n data: ScanRefreshWorkerRunRequest,\n progressEmitter: MonotonicValueSampler<AgentScanProgress>,\n): Promise<void> {\n const startedAt = performance.now();\n const baseline = baselineFor(data);\n const { agent } = baseline;\n const previousSessions = baseline.sessions;\n const previousMeta = baseline.meta;\n const operation = data.operation;\n const sourceSynchronization = synchronizesSessionSources(operation);\n const backfill = isBackfillOperation(operation);\n const durableCheckpoints = usesDurableCheckpoints(operation);\n const backfillCursor = backfill ? operation.cursor : undefined;\n\n appLogger.debug(\"scan.refresh_worker.started\", {\n agent: data.agentName,\n operation: operation.kind,\n backfill_cursor: backfillCursor ?? undefined,\n changed_ids: operation.kind === \"incremental-scan\" ? operation.changedIds.length : 0,\n previous_sessions: previousSessions.length,\n });\n\n const reportProgress = (progress: AgentScanProgress): void => {\n progressEmitter.push(progress, progress.phase ?? \"scanning\");\n };\n\n if (!agent.isAvailable()) {\n appLogger.warn(\"scan.refresh_worker.agent_unavailable\", {\n agent: data.agentName,\n operation: operation.kind,\n });\n throw new AgentUnavailableDuringScanError(data.agentName);\n }\n\n let sessions: SessionHead[];\n let changedIds: string[] | undefined;\n let sourceFailures: SessionSourceFailure[] = [];\n let explicitRemovedSessionIds: string[] = [];\n let finalizeSessionIds: ReadonlySet<string> | undefined;\n let backfillOrder: SessionHead[] | undefined;\n let backfillCursorIndex = -1;\n let sourceSynchronizationDetails:\n | {\n sourceCount: number;\n removedCount: number;\n }\n | undefined;\n\n if (operation.kind === \"recompute-derived\") {\n sessions = previousSessions;\n } else if (sourceSynchronization) {\n if (!(agent instanceof FileSystemSessionSource)) {\n throw new Error(`Agent ${agent.name} does not support Session Source synchronization`);\n }\n const result = synchronizeSessionSources(\n agent,\n { sessions: previousSessions, meta: previousMeta },\n {\n kind: \"refresh\",\n scanOptions: { ...data.scanOptions, onProgress: reportProgress },\n },\n );\n sessions = result.sessions;\n changedIds = result.changedSessionIds;\n finalizeSessionIds = new Set(result.finalizeSessionIds);\n sourceSynchronizationDetails = {\n sourceCount: result.sourceCount,\n removedCount: result.removedSourceCount,\n };\n sourceFailures = result.sourceFailures;\n explicitRemovedSessionIds = result.explicitRemovedSessionIds;\n } else if (operation.kind === \"incremental-scan\") {\n changedIds = operation.changedIds;\n sessions = inheritSmartTags(\n await Promise.resolve(\n agent.incrementalScan(previousSessions, operation.changedIds, undefined, {\n ...data.scanOptions,\n onProgress: reportProgress,\n }),\n ),\n previousSessions,\n );\n } else if (agent instanceof FileSystemSessionSource) {\n const result = synchronizeSessionSources(\n agent,\n { sessions: previousSessions, meta: previousMeta },\n {\n kind: \"reload\",\n scanOptions: { ...data.scanOptions, onProgress: reportProgress },\n },\n );\n sessions = result.sessions;\n finalizeSessionIds = new Set(result.finalizeSessionIds);\n sourceFailures = result.sourceFailures;\n explicitRemovedSessionIds = result.explicitRemovedSessionIds;\n } else {\n sessions = inheritSmartTags(\n await Promise.resolve(\n agent.scan({\n ...data.scanOptions,\n onProgress: reportProgress,\n }),\n ),\n previousSessions,\n );\n }\n\n sessions = attachMissingProjectIdentities(sessions);\n const completeness: SessionSnapshotCompleteness =\n data.scanOptions.from == null && data.scanOptions.to == null && sourceFailures.length === 0\n ? \"complete\"\n : \"partial\";\n if (durableCheckpoints) {\n const ordered = sortSessions(sessions);\n parentPort?.postMessage({\n type: \"checkpoint\",\n requestId: data.requestId,\n generation: baseline.generation,\n checkpoint: {\n stage: \"scanned\",\n sessions: ordered,\n meta: buildAgentCacheMeta(agent, new Set(ordered.map((session) => session.id))),\n completeness,\n },\n } satisfies ScanRefreshWorkerMessage);\n sessions = ordered;\n }\n\n if (backfill) {\n const selection = selectBackfillSessions(sessions, changedIds ?? [], backfillCursor);\n sessions = selection.orderedSessions;\n finalizeSessionIds = selection.finalizeSessionIds;\n backfillOrder = selection.orderedSessions;\n backfillCursorIndex = selection.cursorIndex;\n }\n\n const scanDuration = performance.now() - startedAt;\n appLogger.debug(\"scan.refresh_worker.scanned\", {\n agent: data.agentName,\n operation: operation.kind,\n backfill_cursor: backfillCursor ?? undefined,\n sessions: sessions.length,\n changed_ids: changedIds?.length ?? 0,\n source_count: sourceSynchronizationDetails?.sourceCount,\n removed_count: sourceSynchronizationDetails?.removedCount,\n failed_sources: sourceFailures.length,\n duration_ms: Math.round(scanDuration),\n });\n\n const finalizeStartedAt = performance.now();\n const finalizationTiming = createSessionFinalizationTiming();\n const backfillPositionById = backfillOrder\n ? new Map(backfillOrder.map((session, index) => [session.id, index]))\n : undefined;\n sessions = finalizeSessions(\n agent,\n sessions,\n reportProgress,\n durableCheckpoints\n ? (checkpoint) => {\n let nextCheckpoint = checkpoint;\n if (checkpoint.stage === \"finalizing\" && backfillOrder && backfillPositionById) {\n let nextCursorIndex = backfillCursorIndex;\n for (const { session } of checkpoint.changes) {\n const index = backfillPositionById.get(session.id);\n if (index != null && index > nextCursorIndex) nextCursorIndex = index;\n }\n if (nextCursorIndex > backfillCursorIndex) {\n backfillCursorIndex = nextCursorIndex;\n nextCheckpoint = {\n ...checkpoint,\n backfillCursor: backfillOrder[nextCursorIndex]?.id,\n };\n }\n }\n parentPort?.postMessage({\n type: \"checkpoint\",\n requestId: data.requestId,\n generation: baseline.generation,\n checkpoint: nextCheckpoint,\n } satisfies ScanRefreshWorkerMessage);\n }\n : undefined,\n finalizeSessionIds,\n (batchTiming) => {\n finalizationTiming.batches += 1;\n addSessionTagTiming(finalizationTiming, batchTiming);\n appLogger.debug(\"scan.refresh_worker.finalization_batch\", {\n agent: data.agentName,\n batch: finalizationTiming.batches,\n sessions: batchTiming.sessions,\n cache_hits: batchTiming.cacheHits,\n stale_sessions: batchTiming.staleSessions,\n failed_sessions: batchTiming.failedSessions,\n get_session_data_calls: batchTiming.getSessionDataCalls,\n get_session_data_ms: roundMilliseconds(batchTiming.getSessionDataMs),\n classify_session_tags_calls: batchTiming.classifySessionTagsCalls,\n classify_session_tags_ms: roundMilliseconds(batchTiming.classifySessionTagsMs),\n });\n },\n );\n const finalizationDuration = performance.now() - finalizeStartedAt;\n const otherFinalizationMs = Math.max(\n 0,\n finalizationDuration -\n finalizationTiming.getSessionDataMs -\n finalizationTiming.classifySessionTagsMs,\n );\n appLogger.debug(\"scan.refresh_worker.finalized\", {\n agent: data.agentName,\n operation: operation.kind,\n backfill_cursor: backfillOrder?.[backfillCursorIndex]?.id,\n sessions: sessions.length,\n finalized_sessions: finalizationTiming.sessions,\n batches: finalizationTiming.batches,\n cache_hits: finalizationTiming.cacheHits,\n stale_sessions: finalizationTiming.staleSessions,\n failed_sessions: finalizationTiming.failedSessions,\n get_session_data_calls: finalizationTiming.getSessionDataCalls,\n get_session_data_ms: roundMilliseconds(finalizationTiming.getSessionDataMs),\n get_session_data_avg_ms: roundMilliseconds(\n finalizationTiming.getSessionDataCalls > 0\n ? finalizationTiming.getSessionDataMs / finalizationTiming.getSessionDataCalls\n : 0,\n ),\n classify_session_tags_calls: finalizationTiming.classifySessionTagsCalls,\n classify_session_tags_ms: roundMilliseconds(finalizationTiming.classifySessionTagsMs),\n classify_session_tags_avg_ms: roundMilliseconds(\n finalizationTiming.classifySessionTagsCalls > 0\n ? finalizationTiming.classifySessionTagsMs / finalizationTiming.classifySessionTagsCalls\n : 0,\n ),\n other_finalization_ms: roundMilliseconds(otherFinalizationMs),\n duration_ms: roundMilliseconds(finalizationDuration),\n total_duration_ms: Math.round(performance.now() - startedAt),\n });\n const nextMeta = buildAgentCacheMeta(agent, new Set(sessions.map((session) => session.id)));\n const metaDiff = computeCacheMetaDiff(previousMeta, nextMeta);\n const diff = computeSessionDiff(\n previousSessions,\n sessions,\n [...(changedIds ?? []), ...Object.keys(metaDiff.changes), ...metaDiff.removedIds],\n sessionSignature,\n );\n\n baseline.staged = {\n requestId: data.requestId,\n generation: baseline.generation,\n sessions,\n meta: nextMeta,\n };\n progressEmitter.flush();\n parentPort?.postMessage({\n type: \"done\",\n requestId: data.requestId,\n generation: baseline.generation,\n changes: diff.changes,\n removedSessionIds: diff.removedSessionIds,\n meta: metaDiff.changes,\n removedMetaIds: metaDiff.removedIds,\n sourceFailures,\n completeness,\n explicitRemovedSessionIds,\n durationMs: performance.now() - startedAt,\n } satisfies ScanRefreshWorkerMessage);\n}\n\nasync function handleRequest(data: ScanRefreshWorkerRunRequest): Promise<void> {\n const startedAt = performance.now();\n const progressEmitter = new MonotonicValueSampler<AgentScanProgress>(\n PROGRESS_INTERVAL_MS,\n (progress) => {\n parentPort?.postMessage({\n type: \"progress\",\n requestId: data.requestId,\n generation: data.generation ?? 0,\n progress,\n } satisfies ScanRefreshWorkerMessage);\n },\n );\n try {\n synchronizePricingGeneration(data.pricingGenerationId);\n await run(data, progressEmitter);\n } catch (error) {\n progressEmitter.flush();\n postRequestError(data, error, startedAt);\n } finally {\n progressEmitter.cancel();\n }\n}\n\nlet requestTail = Promise.resolve();\n\nfunction commitBaseline(data: ScanRefreshWorkerCommitRequest): void {\n if (!workerBaseline) throw new Error(\"Cannot commit an uninitialized worker baseline\");\n const staged = workerBaseline.staged;\n if (!staged || staged.requestId !== data.requestId) {\n throw new Error(`Worker result ${data.requestId} is not awaiting commit`);\n }\n if (workerBaseline.generation !== data.generation || staged.generation !== data.generation) {\n throw new Error(\n `Worker commit generation mismatch: expected ${workerBaseline.generation}, received ${data.generation}`,\n );\n }\n workerBaseline.sessions = staged.sessions;\n workerBaseline.meta = staged.meta;\n workerBaseline.generation += 1;\n workerBaseline.staged = null;\n}\n\nfunction postRequestError(data: ScanRefreshWorkerRequest, error: unknown, startedAt: number): void {\n const errorCode = error instanceof AgentUnavailableDuringScanError ? error.code : undefined;\n parentPort?.postMessage({\n type: \"error\",\n requestId: data.requestId,\n generation: data.generation,\n error: error instanceof Error ? error.message : String(error),\n ...(errorCode ? { errorCode } : {}),\n durationMs: performance.now() - startedAt,\n } satisfies ScanRefreshWorkerMessage);\n}\n\nfunction handleCommit(data: ScanRefreshWorkerCommitRequest): void {\n const startedAt = performance.now();\n try {\n commitBaseline(data);\n } catch (error) {\n postRequestError(data, error, startedAt);\n }\n}\n\nfunction enqueueRequest(data: ScanRefreshWorkerRequest): void {\n requestTail = requestTail\n .then(() => (data.type === \"commit\" ? handleCommit(data) : handleRequest(data)))\n .catch((error) => {\n appLogger.error(\"scan.refresh_worker.request_error\", {\n request_id: data.requestId,\n request_type: data.type,\n error,\n });\n });\n}\n\nconst initialRequest = workerData as Partial<ScanRefreshWorkerRequest> | undefined;\nif (\n initialRequest?.type === \"run\" &&\n typeof initialRequest.requestId === \"number\" &&\n typeof initialRequest.agentName === \"string\" &&\n typeof initialRequest.pricingGenerationId === \"number\" &&\n initialRequest.operation != null &&\n Array.isArray(initialRequest.previousSessions) &&\n initialRequest.meta != null\n) {\n enqueueRequest(initialRequest as ScanRefreshWorkerRunRequest);\n}\n\nparentPort?.on(\"message\", (message: ScanRefreshWorkerRequest) => {\n enqueueRequest(message);\n});\n","export class MonotonicValueSampler<Value> {\n private phase: string | null = null;\n private lastEmittedAt = -Infinity;\n private pending: Value | undefined;\n private hasPending = false;\n\n constructor(\n private readonly intervalMs: number,\n private readonly emit: (value: Value) => void,\n private readonly now: () => number = () => performance.now(),\n ) {}\n\n push(value: Value, phase: string): void {\n if (this.phase !== phase) {\n this.flush();\n this.phase = phase;\n this.emitNow(value);\n return;\n }\n\n if (this.now() - this.lastEmittedAt >= this.intervalMs) {\n this.pending = undefined;\n this.hasPending = false;\n this.emitNow(value);\n return;\n }\n\n this.pending = value;\n this.hasPending = true;\n }\n\n flush(): void {\n if (!this.hasPending) return;\n const pending = this.pending as Value;\n this.pending = undefined;\n this.hasPending = false;\n this.emitNow(pending);\n }\n\n cancel(): void {\n this.phase = null;\n this.lastEmittedAt = -Infinity;\n this.pending = undefined;\n this.hasPending = false;\n }\n\n private emitNow(value: Value): void {\n this.lastEmittedAt = this.now();\n this.emit(value);\n }\n}\n","type DurableCheckpoint = { checkpoint?: \"durable\" };\n\nexport type ScanRefreshOperation =\n | ({ kind: \"full-scan\" } & DurableCheckpoint)\n | { kind: \"incremental-scan\"; changedIds: string[] }\n | ({ kind: \"source-refresh\" } & DurableCheckpoint)\n | { kind: \"recompute-derived\" }\n | ({ kind: \"full-backfill\"; cursor?: string | null } & DurableCheckpoint)\n | ({ kind: \"source-backfill\"; cursor?: string | null } & DurableCheckpoint);\n\nexport type BackfillScanRefreshOperation = Extract<\n ScanRefreshOperation,\n { kind: \"full-backfill\" | \"source-backfill\" }\n>;\n\nexport function synchronizesSessionSources(operation: ScanRefreshOperation): boolean {\n return operation.kind === \"source-refresh\" || operation.kind === \"source-backfill\";\n}\n\nexport function isBackfillOperation(\n operation: ScanRefreshOperation,\n): operation is BackfillScanRefreshOperation {\n return operation.kind === \"full-backfill\" || operation.kind === \"source-backfill\";\n}\n\nexport function usesDurableCheckpoints(operation: ScanRefreshOperation): boolean {\n return \"checkpoint\" in operation && operation.checkpoint === \"durable\";\n}\n"],"mappings":"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","names":["now"]}
1
+ {"version":3,"sources":["../src/scan-refresh-worker.ts","../src/monotonic-value-sampler.ts","../src/scan-refresh-delta.ts","../src/scan-refresh-operation.ts"],"sourcesContent":["import \"./diagnostics-bridge.js\";\nimport { parentPort, workerData } from \"node:worker_threads\";\nimport {\n attachMissingProjectIdentities,\n buildAgentCacheMeta,\n ensureSessionTagsSync,\n executeAgentScanPlan,\n hasStaleSessionTags,\n planAgentScan,\n sortSessions,\n type ScanOptions,\n type SessionHead,\n type PersistedSessionHeadChange,\n type SessionSnapshotCompleteness,\n type SessionTagTiming,\n} from \"@codesesh/core/runtime/discovery\";\nimport {\n createRegisteredAgents,\n type AgentScanProgress,\n type BaseAgent,\n type SessionCacheMeta,\n type SessionSourceFailure,\n} from \"@codesesh/core/runtime/agents\";\nimport { synchronizePricingGeneration } from \"@codesesh/core/runtime/pricing\";\nimport { appLogger, type LogContext } from \"./logging.js\";\nimport { acknowledgeWorkerLogDrain } from \"./worker-log-drain.js\";\nimport { MonotonicValueSampler } from \"./monotonic-value-sampler.js\";\nimport { buildScanRefreshDelta } from \"./scan-refresh-delta.js\";\nimport {\n AgentUnavailableDuringScanError,\n type ScanRefreshWorkerErrorCode,\n} from \"./scan-refresh-error.js\";\nimport {\n isBackfillOperation,\n scanIntentForOperation,\n usesDurableCheckpoints,\n type ScanRefreshOperation,\n} from \"./scan-refresh-operation.js\";\n\nexport type ScanRefreshWorkerMessage =\n | {\n type: \"progress\";\n requestId: number;\n generation: number;\n progress: AgentScanProgress;\n }\n | {\n type: \"checkpoint\";\n requestId: number;\n generation: number;\n checkpoint: ScanRefreshWorkerCheckpoint;\n }\n | {\n type: \"done\";\n requestId: number;\n generation: number;\n changes: PersistedSessionHeadChange[];\n removedSessionIds: string[];\n meta: Record<string, SessionCacheMeta>;\n removedMetaIds: string[];\n sourceFailures: SessionSourceFailure[];\n completeness: SessionSnapshotCompleteness;\n explicitRemovedSessionIds: string[];\n durationMs: number;\n }\n | {\n type: \"error\";\n requestId: number;\n generation: number;\n error: string;\n errorCode?: ScanRefreshWorkerErrorCode;\n durationMs: number;\n };\n\nexport type ScanRefreshWorkerCheckpoint =\n | {\n stage: \"scanned\";\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n completeness: SessionSnapshotCompleteness;\n }\n | {\n stage: \"finalizing\";\n changes: PersistedSessionHeadChange[];\n meta: Record<string, SessionCacheMeta>;\n backfillCursor?: string;\n };\n\nexport interface ScanRefreshWorkerRunRequest {\n type: \"run\";\n requestId: number;\n agentName: string;\n generation: number;\n pricingGenerationId: number;\n previousSessions?: SessionHead[];\n operation: ScanRefreshOperation;\n scanOptions: Pick<ScanOptions, \"from\" | \"to\" | \"fast\">;\n meta?: Record<string, SessionCacheMeta>;\n logContext?: LogContext;\n}\n\nexport interface ScanRefreshWorkerCommitRequest {\n type: \"commit\";\n requestId: number;\n generation: number;\n logContext?: LogContext;\n}\n\nexport type ScanRefreshWorkerRequest = ScanRefreshWorkerRunRequest | ScanRefreshWorkerCommitRequest;\n\ninterface StagedWorkerBaseline {\n requestId: number;\n generation: number;\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n}\n\ninterface WorkerBaseline {\n agentName: string;\n agent: BaseAgent;\n generation: number;\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n staged: StagedWorkerBaseline | null;\n}\n\ninterface BackfillSelection {\n orderedSessions: SessionHead[];\n finalizeSessionIds: ReadonlySet<string>;\n cursorIndex: number;\n}\n\nfunction selectBackfillSessions(\n sessions: SessionHead[],\n changedIds: string[],\n cursor: string | null | undefined,\n): BackfillSelection {\n const orderedSessions = sortSessions(sessions);\n const cursorIndex = cursor\n ? orderedSessions.findIndex((session) => session.reference.sessionId === cursor)\n : -1;\n const finalizeSessionIds = new Set<string>();\n const startIndex = cursorIndex >= 0 ? cursorIndex + 1 : 0;\n\n for (let index = startIndex; index < orderedSessions.length; index += 1) {\n finalizeSessionIds.add(orderedSessions[index]!.reference.sessionId);\n }\n\n for (const changedId of changedIds) finalizeSessionIds.add(changedId);\n\n // A hot session before the cursor remains stale until it settles. Keep it in\n // the next pass so it is not permanently skipped when it becomes idle.\n for (let index = 0; index <= cursorIndex; index += 1) {\n const session = orderedSessions[index]!;\n if (hasStaleSessionTags(session)) finalizeSessionIds.add(session.reference.sessionId);\n }\n\n return { orderedSessions, finalizeSessionIds, cursorIndex };\n}\n\n/**\n * A session still receiving writes will be stale again within seconds, so\n * recomputing its tags every refresh cycle is wasted work — wait for it to\n * settle before paying the getSessionData() parse cost.\n */\nconst TAG_SETTLE_MS = 60_000;\nconst TAG_CHECKPOINT_SIZE = 32;\nconst PROGRESS_INTERVAL_MS = 100;\n\ninterface SessionFinalizationTiming extends SessionTagTiming {\n batches: number;\n}\n\nfunction createSessionFinalizationTiming(): SessionFinalizationTiming {\n return {\n batches: 0,\n sessions: 0,\n cacheHits: 0,\n staleSessions: 0,\n failedSessions: 0,\n getSessionDataCalls: 0,\n getSessionDataMs: 0,\n classifySessionTagsCalls: 0,\n classifySessionTagsMs: 0,\n };\n}\n\nfunction addSessionTagTiming(target: SessionFinalizationTiming, source: SessionTagTiming): void {\n target.sessions += source.sessions;\n target.cacheHits += source.cacheHits;\n target.staleSessions += source.staleSessions;\n target.failedSessions += source.failedSessions;\n target.getSessionDataCalls += source.getSessionDataCalls;\n target.getSessionDataMs += source.getSessionDataMs;\n target.classifySessionTagsCalls += source.classifySessionTagsCalls;\n target.classifySessionTagsMs += source.classifySessionTagsMs;\n}\n\nfunction roundMilliseconds(value: number): number {\n return Math.round(value * 100) / 100;\n}\n\nfunction isSettled(session: SessionHead, now: number): boolean {\n return now - (session.time_updated ?? session.time_created) >= TAG_SETTLE_MS;\n}\n\n/**\n * Runs identity resolution (spawns git) and stale smart-tag reclassification\n * on the worker thread, off the server's main event loop.\n */\nexport function finalizeSessions(\n agent: BaseAgent,\n sessions: SessionHead[],\n onProgress?: (progress: AgentScanProgress) => void,\n onCheckpoint?: (checkpoint: ScanRefreshWorkerCheckpoint) => void,\n finalizeSessionIds?: ReadonlySet<string>,\n onTiming?: (timing: SessionTagTiming) => void,\n): SessionHead[] {\n const ordered = sortSessions(attachMissingProjectIdentities(sessions));\n\n const now = Date.now();\n const settled = ordered.filter(\n (session) =>\n (!finalizeSessionIds || finalizeSessionIds.has(session.reference.sessionId)) &&\n isSettled(session, now),\n );\n if (settled.length === 0) return ordered;\n\n let lastReportedAt = -Infinity;\n const reportProgress = (processed: number, total: number): void => {\n const now = performance.now();\n if (processed !== 0 && processed !== total && now - lastReportedAt < 100) return;\n lastReportedAt = now;\n onProgress?.({\n phase: \"finalizing\",\n total,\n processed,\n sessions: ordered.length,\n });\n };\n reportProgress(0, settled.length);\n\n const sortIndexById = new Map(\n ordered.map((session, index) => [session.reference.sessionId, index]),\n );\n const taggedById = new Map<string, SessionHead>();\n for (let start = 0; start < settled.length; start += TAG_CHECKPOINT_SIZE) {\n const batch = settled.slice(start, start + TAG_CHECKPOINT_SIZE);\n const taggedResult = ensureSessionTagsSync(agent, batch, (processed) => {\n reportProgress(start + processed, settled.length);\n });\n if (taggedResult.timing) onTiming?.(taggedResult.timing);\n const taggedBatch = taggedResult.sessions;\n for (const session of taggedBatch) taggedById.set(session.reference.sessionId, session);\n\n onCheckpoint?.({\n stage: \"finalizing\",\n changes: taggedBatch.map((session) => ({\n session,\n sortIndex: sortIndexById.get(session.reference.sessionId) ?? 0,\n })),\n meta: buildAgentCacheMeta(\n agent,\n new Set(taggedBatch.map((session) => session.reference.sessionId)),\n ),\n });\n }\n return ordered.map((session) => taggedById.get(session.reference.sessionId) ?? session);\n}\n\nlet workerBaseline: WorkerBaseline | null = null;\n\nfunction baselineFor(data: ScanRefreshWorkerRunRequest): WorkerBaseline {\n const generation = data.generation ?? 0;\n const hasSessions = Array.isArray(data.previousSessions);\n const hasMeta = data.meta != null;\n if (hasSessions !== hasMeta)\n throw new Error(\"Worker baseline requires sessions and meta together\");\n\n if (hasSessions && hasMeta) {\n if (workerBaseline) throw new Error(\"Scan refresh worker baseline is already initialized\");\n const agent = createRegisteredAgents().find((item) => item.name === data.agentName);\n if (!agent) throw new Error(`Unknown agent: ${data.agentName}`);\n workerBaseline = {\n agentName: data.agentName,\n agent,\n generation,\n sessions: data.previousSessions!,\n meta: data.meta!,\n staged: null,\n };\n }\n\n if (!workerBaseline) throw new Error(\"Scan refresh worker baseline is not initialized\");\n if (workerBaseline.agentName !== data.agentName) {\n throw new Error(`Worker Agent mismatch: expected ${workerBaseline.agentName}`);\n }\n if (workerBaseline.generation !== generation) {\n throw new Error(\n `Worker generation mismatch: expected ${workerBaseline.generation}, received ${generation}`,\n );\n }\n if (workerBaseline.staged) {\n throw new Error(`Worker result ${workerBaseline.staged.requestId} is awaiting commit`);\n }\n\n workerBaseline.agent.restoreSessionCacheMeta(workerBaseline.meta);\n return workerBaseline;\n}\n\nasync function run(\n data: ScanRefreshWorkerRunRequest,\n progressEmitter: MonotonicValueSampler<AgentScanProgress>,\n): Promise<void> {\n const startedAt = performance.now();\n const baseline = baselineFor(data);\n const { agent } = baseline;\n const previousSessions = baseline.sessions;\n const previousMeta = baseline.meta;\n const operation = data.operation;\n const backfill = isBackfillOperation(operation);\n const scanPlan = planAgentScan(agent.sessionSourceAccess, scanIntentForOperation(operation));\n const durableCheckpoints = usesDurableCheckpoints(operation);\n const backfillCursor = backfill ? operation.cursor : undefined;\n\n appLogger.debug(\"scan.refresh_worker.started\", {\n agent: data.agentName,\n operation: operation.kind,\n backfill_cursor: backfillCursor ?? undefined,\n previous_sessions: previousSessions.length,\n });\n\n const reportProgress = (progress: AgentScanProgress): void => {\n progressEmitter.push(progress, progress.phase ?? \"scanning\");\n };\n\n if (!agent.isAvailable()) {\n appLogger.warn(\"scan.refresh_worker.agent_unavailable\", {\n agent: data.agentName,\n operation: operation.kind,\n });\n throw new AgentUnavailableDuringScanError(data.agentName);\n }\n\n if (scanPlan.kind === \"check-for-changes\") {\n throw new Error(`Change checks must run before dispatching Agent ${agent.name} to the worker`);\n }\n const execution = executeAgentScanPlan(\n agent,\n scanPlan,\n { sessions: previousSessions, meta: previousMeta },\n { ...data.scanOptions, onProgress: reportProgress },\n );\n let sessions = execution.sessions;\n const changedIds = execution.changedSessionIds;\n const sourceFailures = execution.sourceFailures;\n const explicitRemovedSessionIds = execution.explicitRemovedSessionIds;\n let finalizeSessionIds: ReadonlySet<string> | undefined =\n execution.finalizeSessionIds === undefined ? undefined : new Set(execution.finalizeSessionIds);\n let backfillOrder: SessionHead[] | undefined;\n let backfillCursorIndex = -1;\n const sourceSynchronizationDetails = execution.sourceSynchronization\n ? {\n sourceCount: execution.sourceSynchronization.sourceCount,\n removedCount: execution.sourceSynchronization.removedSourceCount,\n enumerationMs: execution.sourceSynchronization.timing.enumerationMs,\n diffMs: execution.sourceSynchronization.timing.diffMs,\n parseMs: execution.sourceSynchronization.timing.parseMs,\n changedCount: execution.sourceSynchronization.timing.changedSourceCount,\n processedCount: execution.sourceSynchronization.timing.processedSourceCount,\n }\n : undefined;\n\n sessions = attachMissingProjectIdentities(sessions);\n const completeness = execution.completeness;\n if (durableCheckpoints) {\n const ordered = sortSessions(sessions);\n parentPort?.postMessage({\n type: \"checkpoint\",\n requestId: data.requestId,\n generation: baseline.generation,\n checkpoint: {\n stage: \"scanned\",\n sessions: ordered,\n meta: buildAgentCacheMeta(\n agent,\n new Set(ordered.map((session) => session.reference.sessionId)),\n ),\n completeness,\n },\n } satisfies ScanRefreshWorkerMessage);\n sessions = ordered;\n }\n\n if (backfill) {\n const selection = selectBackfillSessions(sessions, changedIds ?? [], backfillCursor);\n sessions = selection.orderedSessions;\n finalizeSessionIds = selection.finalizeSessionIds;\n backfillOrder = selection.orderedSessions;\n backfillCursorIndex = selection.cursorIndex;\n }\n\n const scanDuration = performance.now() - startedAt;\n appLogger.debug(\"scan.refresh_worker.scanned\", {\n agent: data.agentName,\n operation: operation.kind,\n backfill_cursor: backfillCursor ?? undefined,\n sessions: sessions.length,\n changed_ids: changedIds?.length ?? 0,\n source_count: sourceSynchronizationDetails?.sourceCount,\n removed_count: sourceSynchronizationDetails?.removedCount,\n source_enumeration_ms: roundMilliseconds(sourceSynchronizationDetails?.enumerationMs ?? 0),\n source_diff_ms: roundMilliseconds(sourceSynchronizationDetails?.diffMs ?? 0),\n source_parse_ms: roundMilliseconds(sourceSynchronizationDetails?.parseMs ?? 0),\n changed_sources: sourceSynchronizationDetails?.changedCount,\n processed_sources: sourceSynchronizationDetails?.processedCount,\n failed_sources: sourceFailures.length,\n duration_ms: Math.round(scanDuration),\n });\n\n const finalizeStartedAt = performance.now();\n const finalizationTiming = createSessionFinalizationTiming();\n const backfillPositionById = backfillOrder\n ? new Map(backfillOrder.map((session, index) => [session.reference.sessionId, index]))\n : undefined;\n sessions = finalizeSessions(\n agent,\n sessions,\n reportProgress,\n durableCheckpoints\n ? (checkpoint) => {\n let nextCheckpoint = checkpoint;\n if (checkpoint.stage === \"finalizing\" && backfillOrder && backfillPositionById) {\n let nextCursorIndex = backfillCursorIndex;\n for (const { session } of checkpoint.changes) {\n const index = backfillPositionById.get(session.reference.sessionId);\n if (index != null && index > nextCursorIndex) nextCursorIndex = index;\n }\n if (nextCursorIndex > backfillCursorIndex) {\n backfillCursorIndex = nextCursorIndex;\n nextCheckpoint = {\n ...checkpoint,\n backfillCursor: backfillOrder[nextCursorIndex]?.reference.sessionId,\n };\n }\n }\n parentPort?.postMessage({\n type: \"checkpoint\",\n requestId: data.requestId,\n generation: baseline.generation,\n checkpoint: nextCheckpoint,\n } satisfies ScanRefreshWorkerMessage);\n }\n : undefined,\n finalizeSessionIds,\n (batchTiming) => {\n finalizationTiming.batches += 1;\n addSessionTagTiming(finalizationTiming, batchTiming);\n appLogger.debug(\"scan.refresh_worker.finalization_batch\", {\n agent: data.agentName,\n batch: finalizationTiming.batches,\n sessions: batchTiming.sessions,\n cache_hits: batchTiming.cacheHits,\n stale_sessions: batchTiming.staleSessions,\n failed_sessions: batchTiming.failedSessions,\n get_session_data_calls: batchTiming.getSessionDataCalls,\n get_session_data_ms: roundMilliseconds(batchTiming.getSessionDataMs),\n classify_session_tags_calls: batchTiming.classifySessionTagsCalls,\n classify_session_tags_ms: roundMilliseconds(batchTiming.classifySessionTagsMs),\n });\n },\n );\n const finalizationDuration = performance.now() - finalizeStartedAt;\n const otherFinalizationMs = Math.max(\n 0,\n finalizationDuration -\n finalizationTiming.getSessionDataMs -\n finalizationTiming.classifySessionTagsMs,\n );\n appLogger.debug(\"scan.refresh_worker.finalized\", {\n agent: data.agentName,\n operation: operation.kind,\n backfill_cursor: backfillOrder?.[backfillCursorIndex]?.reference.sessionId,\n sessions: sessions.length,\n finalized_sessions: finalizationTiming.sessions,\n batches: finalizationTiming.batches,\n cache_hits: finalizationTiming.cacheHits,\n stale_sessions: finalizationTiming.staleSessions,\n failed_sessions: finalizationTiming.failedSessions,\n get_session_data_calls: finalizationTiming.getSessionDataCalls,\n get_session_data_ms: roundMilliseconds(finalizationTiming.getSessionDataMs),\n get_session_data_avg_ms: roundMilliseconds(\n finalizationTiming.getSessionDataCalls > 0\n ? finalizationTiming.getSessionDataMs / finalizationTiming.getSessionDataCalls\n : 0,\n ),\n classify_session_tags_calls: finalizationTiming.classifySessionTagsCalls,\n classify_session_tags_ms: roundMilliseconds(finalizationTiming.classifySessionTagsMs),\n classify_session_tags_avg_ms: roundMilliseconds(\n finalizationTiming.classifySessionTagsCalls > 0\n ? finalizationTiming.classifySessionTagsMs / finalizationTiming.classifySessionTagsCalls\n : 0,\n ),\n other_finalization_ms: roundMilliseconds(otherFinalizationMs),\n duration_ms: roundMilliseconds(finalizationDuration),\n total_duration_ms: Math.round(performance.now() - startedAt),\n });\n const nextMeta = buildAgentCacheMeta(\n agent,\n new Set(sessions.map((session) => session.reference.sessionId)),\n );\n const delta = buildScanRefreshDelta({\n previousSessions,\n sessions,\n previousMeta,\n nextMeta,\n changedIds,\n completeness,\n explicitRemovedSessionIds,\n });\n\n baseline.staged = {\n requestId: data.requestId,\n generation: baseline.generation,\n sessions,\n meta: nextMeta,\n };\n progressEmitter.flush();\n parentPort?.postMessage({\n type: \"done\",\n requestId: data.requestId,\n generation: baseline.generation,\n ...delta,\n sourceFailures,\n completeness,\n explicitRemovedSessionIds,\n durationMs: performance.now() - startedAt,\n } satisfies ScanRefreshWorkerMessage);\n}\n\nasync function handleRequest(data: ScanRefreshWorkerRunRequest): Promise<void> {\n const startedAt = performance.now();\n const progressEmitter = new MonotonicValueSampler<AgentScanProgress>(\n PROGRESS_INTERVAL_MS,\n (progress) => {\n parentPort?.postMessage({\n type: \"progress\",\n requestId: data.requestId,\n generation: data.generation ?? 0,\n progress,\n } satisfies ScanRefreshWorkerMessage);\n },\n );\n try {\n synchronizePricingGeneration(data.pricingGenerationId);\n await run(data, progressEmitter);\n } catch (error) {\n progressEmitter.flush();\n postRequestError(data, error, startedAt);\n } finally {\n progressEmitter.cancel();\n }\n}\n\nlet requestTail = Promise.resolve();\n\nfunction commitBaseline(data: ScanRefreshWorkerCommitRequest): void {\n if (!workerBaseline) throw new Error(\"Cannot commit an uninitialized worker baseline\");\n const staged = workerBaseline.staged;\n if (!staged || staged.requestId !== data.requestId) {\n throw new Error(`Worker result ${data.requestId} is not awaiting commit`);\n }\n if (workerBaseline.generation !== data.generation || staged.generation !== data.generation) {\n throw new Error(\n `Worker commit generation mismatch: expected ${workerBaseline.generation}, received ${data.generation}`,\n );\n }\n workerBaseline.sessions = staged.sessions;\n workerBaseline.meta = staged.meta;\n workerBaseline.generation += 1;\n workerBaseline.staged = null;\n}\n\nfunction postRequestError(data: ScanRefreshWorkerRequest, error: unknown, startedAt: number): void {\n const errorCode = error instanceof AgentUnavailableDuringScanError ? error.code : undefined;\n parentPort?.postMessage({\n type: \"error\",\n requestId: data.requestId,\n generation: data.generation,\n error: error instanceof Error ? error.message : String(error),\n ...(errorCode ? { errorCode } : {}),\n durationMs: performance.now() - startedAt,\n } satisfies ScanRefreshWorkerMessage);\n}\n\nfunction handleCommit(data: ScanRefreshWorkerCommitRequest): void {\n const startedAt = performance.now();\n try {\n commitBaseline(data);\n } catch (error) {\n postRequestError(data, error, startedAt);\n }\n}\n\nfunction enqueueRequest(data: ScanRefreshWorkerRequest): void {\n requestTail = requestTail\n .then(() =>\n appLogger.restoreContext(data.logContext ?? {}, () =>\n data.type === \"commit\" ? handleCommit(data) : handleRequest(data),\n ),\n )\n .catch((error) => {\n appLogger.error(\"scan.refresh_worker.request_error\", {\n request_id: data.requestId,\n request_type: data.type,\n error,\n });\n });\n}\n\nconst initialRequest = workerData as Partial<ScanRefreshWorkerRequest> | undefined;\nif (\n initialRequest?.type === \"run\" &&\n typeof initialRequest.requestId === \"number\" &&\n typeof initialRequest.agentName === \"string\" &&\n typeof initialRequest.pricingGenerationId === \"number\" &&\n initialRequest.operation != null &&\n Array.isArray(initialRequest.previousSessions) &&\n initialRequest.meta != null\n) {\n enqueueRequest(initialRequest as ScanRefreshWorkerRunRequest);\n}\n\nconst workerPort = parentPort;\nworkerPort?.on(\"message\", (message: unknown) => {\n if (acknowledgeWorkerLogDrain(workerPort, message, requestTail)) return;\n enqueueRequest(message as ScanRefreshWorkerRequest);\n});\n","export class MonotonicValueSampler<Value> {\n private phase: string | null = null;\n private lastEmittedAt = -Infinity;\n private pending: Value | undefined;\n private hasPending = false;\n\n constructor(\n private readonly intervalMs: number,\n private readonly emit: (value: Value) => void,\n private readonly now: () => number = () => performance.now(),\n ) {}\n\n push(value: Value, phase: string): void {\n if (this.phase !== phase) {\n this.flush();\n this.phase = phase;\n this.emitNow(value);\n return;\n }\n\n if (this.now() - this.lastEmittedAt >= this.intervalMs) {\n this.pending = undefined;\n this.hasPending = false;\n this.emitNow(value);\n return;\n }\n\n this.pending = value;\n this.hasPending = true;\n }\n\n flush(): void {\n if (!this.hasPending) return;\n const pending = this.pending as Value;\n this.pending = undefined;\n this.hasPending = false;\n this.emitNow(pending);\n }\n\n cancel(): void {\n this.phase = null;\n this.lastEmittedAt = -Infinity;\n this.pending = undefined;\n this.hasPending = false;\n }\n\n private emitNow(value: Value): void {\n this.lastEmittedAt = this.now();\n this.emit(value);\n }\n}\n","import { isDeepStrictEqual } from \"node:util\";\nimport {\n buildSessionPersistenceDiff,\n type PersistedSessionHeadChange,\n type SessionHead,\n type SessionSnapshotCompleteness,\n} from \"@codesesh/core/runtime/discovery\";\nimport { type SessionCacheMeta } from \"@codesesh/core/runtime/agents\";\n\ninterface ScanRefreshDeltaInput {\n previousSessions: SessionHead[];\n sessions: SessionHead[];\n previousMeta: Record<string, SessionCacheMeta>;\n nextMeta: Record<string, SessionCacheMeta>;\n changedIds?: string[];\n completeness: SessionSnapshotCompleteness;\n explicitRemovedSessionIds: string[];\n}\n\nexport interface ScanRefreshDelta {\n changes: PersistedSessionHeadChange[];\n removedSessionIds: string[];\n meta: Record<string, SessionCacheMeta>;\n removedMetaIds: string[];\n}\n\nexport function buildScanRefreshDelta(input: ScanRefreshDeltaInput): ScanRefreshDelta {\n const meta: Record<string, SessionCacheMeta> = {};\n const removedMetaIds: string[] = [];\n for (const [id, value] of Object.entries(input.nextMeta)) {\n if (!isDeepStrictEqual(input.previousMeta[id], value)) meta[id] = value;\n }\n for (const id of Object.keys(input.previousMeta)) {\n if (!Object.hasOwn(input.nextMeta, id)) removedMetaIds.push(id);\n }\n\n const diff = buildSessionPersistenceDiff(input.previousSessions, input.sessions, {\n candidateChangedIds: [...(input.changedIds ?? []), ...Object.keys(meta), ...removedMetaIds],\n completeness: input.completeness,\n explicitRemovedSessionIds: input.explicitRemovedSessionIds,\n });\n return {\n changes: diff.changedSessions,\n removedSessionIds: diff.removedSessionIds,\n meta,\n removedMetaIds,\n };\n}\n","import type { AgentScanIntent } from \"@codesesh/core/runtime/discovery\";\n\ntype DurableCheckpoint = { checkpoint?: \"durable\" };\n\nexport type ScanRefreshOperation =\n | ({ kind: \"full-scan\" } & DurableCheckpoint)\n | ({ kind: \"source-refresh\" } & DurableCheckpoint)\n | { kind: \"recompute-derived\" }\n | ({ kind: \"backfill\"; cursor?: string | null } & DurableCheckpoint);\n\nexport type BackfillScanRefreshOperation = Extract<ScanRefreshOperation, { kind: \"backfill\" }>;\n\nexport function isBackfillOperation(\n operation: ScanRefreshOperation,\n): operation is BackfillScanRefreshOperation {\n return operation.kind === \"backfill\";\n}\n\nexport function usesDurableCheckpoints(operation: ScanRefreshOperation): boolean {\n return \"checkpoint\" in operation && operation.checkpoint === \"durable\";\n}\n\nexport function scanIntentForOperation(operation: ScanRefreshOperation): AgentScanIntent {\n switch (operation.kind) {\n case \"full-scan\":\n return \"reload\";\n case \"source-refresh\":\n return \"refresh\";\n case \"recompute-derived\":\n return \"recompute-derived\";\n case \"backfill\":\n return \"backfill\";\n }\n}\n"],"mappings":"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","names":["now"]}