codesesh 1.0.2 → 1.0.4

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 (64) hide show
  1. package/README.md +18 -10
  2. package/dist/chunk-3SXCTDD6.js +326 -0
  3. package/dist/chunk-3SXCTDD6.js.map +1 -0
  4. package/dist/chunk-BYB77UAJ.js +6054 -0
  5. package/dist/chunk-BYB77UAJ.js.map +1 -0
  6. package/dist/{chunk-PROMURPM.js → chunk-G4HRD3AR.js} +13 -8
  7. package/dist/chunk-G4HRD3AR.js.map +1 -0
  8. package/dist/chunk-MBZ4VV4C.js +670 -0
  9. package/dist/chunk-MBZ4VV4C.js.map +1 -0
  10. package/dist/chunk-QH2HOXJH.js +2 -0
  11. package/dist/chunk-RF3EEWPH.js +17 -0
  12. package/dist/chunk-RF3EEWPH.js.map +1 -0
  13. package/dist/chunk-W4PZHL2C.js +2035 -0
  14. package/dist/chunk-W4PZHL2C.js.map +1 -0
  15. package/dist/chunk-YCUN52HA.js +8422 -0
  16. package/dist/chunk-YCUN52HA.js.map +1 -0
  17. package/dist/discovery-K3GLISI6.js +102 -0
  18. package/dist/discovery-K3GLISI6.js.map +1 -0
  19. package/dist/index.js +3016 -1392
  20. package/dist/index.js.map +1 -1
  21. package/dist/project-identity-worker.js +29 -0
  22. package/dist/project-identity-worker.js.map +1 -0
  23. package/dist/scan-refresh-worker.js +129 -139
  24. package/dist/scan-refresh-worker.js.map +1 -1
  25. package/dist/search-index-worker.js +39 -13
  26. package/dist/search-index-worker.js.map +1 -1
  27. package/dist/smart-tag-worker.js +8 -5
  28. package/dist/smart-tag-worker.js.map +1 -1
  29. package/dist/web/assets/InteractiveReceipt-Dk50TBsH.js +1 -0
  30. package/dist/web/assets/OverviewScreen-5hvQVp4H.js +1 -0
  31. package/dist/web/assets/{PrismHighlighter-BZkkX0AU.js → PrismHighlighter-B1a2dPJO.js} +2 -2
  32. package/dist/web/assets/Projects-Cy_v2yep.js +1 -0
  33. package/dist/web/assets/SearchResultsPanel-DfheEwpz.js +1 -0
  34. package/dist/web/assets/SessionDetail-DRI8R3st.js +53 -0
  35. package/dist/web/assets/api-GP9UCedC.js +1 -0
  36. package/dist/web/assets/contract-xJyW5u7a.js +2 -0
  37. package/dist/web/assets/index-Bd-YkWkZ.css +1 -0
  38. package/dist/web/assets/index-DEjvzumm.js +1410 -0
  39. package/dist/web/assets/panel-ND0J63d3.js +1 -0
  40. package/dist/web/assets/{session-indexes-0oT5HSS5.js → session-indexes-BsgjUoc1.js} +2 -2
  41. package/dist/web/assets/utils-C7BqyxxV.js +1 -0
  42. package/dist/web/index.html +7 -11
  43. package/package.json +4 -10
  44. package/dist/chunk-PROMURPM.js.map +0 -1
  45. package/dist/chunk-VAUC2W7I.js +0 -16119
  46. package/dist/chunk-VAUC2W7I.js.map +0 -1
  47. package/dist/dist-6QTGTYZT.js +0 -175
  48. package/dist/web/assets/ErrorBoundary-D11tWzfn.js +0 -1
  49. package/dist/web/assets/InteractiveReceipt-DYGyHeZd.js +0 -1
  50. package/dist/web/assets/OverviewScreen-DriPmCam.js +0 -1
  51. package/dist/web/assets/Projects-BPDIcUBK.js +0 -1
  52. package/dist/web/assets/SearchFilterBar-Bx73B5e9.js +0 -1
  53. package/dist/web/assets/SearchResultsPanel-A6_3TPhW.js +0 -1
  54. package/dist/web/assets/SessionDetail-BnpvDwtH.js +0 -54
  55. package/dist/web/assets/SmartTagChips-ux6idUGJ.js +0 -1
  56. package/dist/web/assets/agents-BkRP_ww3.js +0 -1
  57. package/dist/web/assets/code-metrics-UYFsCC7E.js +0 -1
  58. package/dist/web/assets/contract-V6QuD0UY.js +0 -1
  59. package/dist/web/assets/index-99ZxpV2y.js +0 -1410
  60. package/dist/web/assets/index-B2RqUgZ5.css +0 -1
  61. package/dist/web/assets/panel-C-gc79Gz.js +0 -1
  62. package/dist/web/assets/session-title-DdtlxtlR.js +0 -1
  63. package/dist/web/assets/utils-DgUgu15E.js +0 -1
  64. /package/dist/{dist-6QTGTYZT.js.map → chunk-QH2HOXJH.js.map} +0 -0
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ import "./chunk-MBZ4VV4C.js";
3
+ import "./chunk-G4HRD3AR.js";
4
+ import {
5
+ computeIdentityProjection
6
+ } from "./chunk-3SXCTDD6.js";
7
+ import "./chunk-W4PZHL2C.js";
8
+
9
+ // src/project-identity-worker.ts
10
+ import { parentPort } from "worker_threads";
11
+ function resolveIdentity(request) {
12
+ try {
13
+ parentPort?.postMessage({
14
+ type: "resolved",
15
+ requestId: request.requestId,
16
+ projection: computeIdentityProjection(request.cwd)
17
+ });
18
+ } catch (error) {
19
+ parentPort?.postMessage({
20
+ type: "failed",
21
+ requestId: request.requestId,
22
+ error: error instanceof Error ? error.message : String(error)
23
+ });
24
+ }
25
+ }
26
+ parentPort?.on("message", (message) => {
27
+ if (message.type === "resolve") resolveIdentity(message);
28
+ });
29
+ //# sourceMappingURL=project-identity-worker.js.map
@@ -0,0 +1 @@
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":[]}
@@ -1,24 +1,31 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ AgentUnavailableDuringScanError
4
+ } from "./chunk-RF3EEWPH.js";
5
+ import "./chunk-QH2HOXJH.js";
2
6
  import {
3
7
  appLogger
4
- } from "./chunk-PROMURPM.js";
8
+ } from "./chunk-G4HRD3AR.js";
5
9
  import {
6
- FileSystemSessionSource,
7
- SMART_TAG_CLASSIFIER_REVISION,
8
10
  attachMissingProjectIdentities,
9
11
  buildAgentCacheMeta,
10
- computeSessionDiff,
11
- createRegisteredAgents,
12
+ buildSessionPersistenceDiff,
12
13
  ensureSessionTagsSync,
13
- sessionSignature,
14
- sortSessions,
15
- synchronizePricingGeneration,
16
- synchronizeSessionSources
17
- } from "./chunk-VAUC2W7I.js";
14
+ executeAgentScanPlan,
15
+ hasStaleSessionTags,
16
+ planAgentScan,
17
+ sortSessions
18
+ } from "./chunk-BYB77UAJ.js";
19
+ import "./chunk-3SXCTDD6.js";
20
+ import {
21
+ createRegisteredAgents
22
+ } from "./chunk-YCUN52HA.js";
23
+ import {
24
+ synchronizePricingGeneration
25
+ } from "./chunk-W4PZHL2C.js";
18
26
 
19
27
  // src/scan-refresh-worker.ts
20
28
  import { parentPort, workerData } from "worker_threads";
21
- import { isDeepStrictEqual } from "util";
22
29
 
23
30
  // src/monotonic-value-sampler.ts
24
31
  var MonotonicValueSampler = class {
@@ -69,62 +76,66 @@ var MonotonicValueSampler = class {
69
76
  }
70
77
  };
71
78
 
72
- // src/scan-refresh-operation.ts
73
- function synchronizesSessionSources(operation) {
74
- return operation.kind === "source-refresh" || operation.kind === "source-backfill";
79
+ // src/scan-refresh-delta.ts
80
+ import { isDeepStrictEqual } from "util";
81
+ function buildScanRefreshDelta(input) {
82
+ const meta = {};
83
+ const removedMetaIds = [];
84
+ for (const [id, value] of Object.entries(input.nextMeta)) {
85
+ if (!isDeepStrictEqual(input.previousMeta[id], value)) meta[id] = value;
86
+ }
87
+ for (const id of Object.keys(input.previousMeta)) {
88
+ if (!Object.hasOwn(input.nextMeta, id)) removedMetaIds.push(id);
89
+ }
90
+ const diff = buildSessionPersistenceDiff(input.previousSessions, input.sessions, {
91
+ candidateChangedIds: [...input.changedIds ?? [], ...Object.keys(meta), ...removedMetaIds],
92
+ completeness: input.completeness,
93
+ explicitRemovedSessionIds: input.explicitRemovedSessionIds
94
+ });
95
+ return {
96
+ changes: diff.changedSessions,
97
+ removedSessionIds: diff.removedSessionIds,
98
+ meta,
99
+ removedMetaIds
100
+ };
75
101
  }
102
+
103
+ // src/scan-refresh-operation.ts
76
104
  function isBackfillOperation(operation) {
77
- return operation.kind === "full-backfill" || operation.kind === "source-backfill";
105
+ return operation.kind === "backfill";
78
106
  }
79
107
  function usesDurableCheckpoints(operation) {
80
108
  return "checkpoint" in operation && operation.checkpoint === "durable";
81
109
  }
82
-
83
- // src/scan-refresh-worker.ts
84
- function computeCacheMetaDiff(previous, next) {
85
- const changes = {};
86
- const removedIds = [];
87
- for (const [id, meta] of Object.entries(next)) {
88
- if (!isDeepStrictEqual(previous[id], meta)) changes[id] = meta;
89
- }
90
- for (const id of Object.keys(previous)) {
91
- if (!Object.hasOwn(next, id)) removedIds.push(id);
110
+ function scanIntentForOperation(operation) {
111
+ switch (operation.kind) {
112
+ case "full-scan":
113
+ return "reload";
114
+ case "source-refresh":
115
+ return "refresh";
116
+ case "recompute-derived":
117
+ return "recompute-derived";
118
+ case "backfill":
119
+ return "backfill";
92
120
  }
93
- return { changes, removedIds };
94
- }
95
- function hasStaleSmartTags(session) {
96
- const sourceUpdatedAt = session.time_updated ?? session.time_created;
97
- return !Array.isArray(session.smart_tags) || session.smart_tags_source_updated_at !== sourceUpdatedAt || session.smart_tags_classifier_revision !== SMART_TAG_CLASSIFIER_REVISION;
98
121
  }
122
+
123
+ // src/scan-refresh-worker.ts
99
124
  function selectBackfillSessions(sessions, changedIds, cursor) {
100
125
  const orderedSessions = sortSessions(sessions);
101
- const cursorIndex = cursor ? orderedSessions.findIndex((session) => session.id === cursor) : -1;
126
+ const cursorIndex = cursor ? orderedSessions.findIndex((session) => session.reference.sessionId === cursor) : -1;
102
127
  const finalizeSessionIds = /* @__PURE__ */ new Set();
103
128
  const startIndex = cursorIndex >= 0 ? cursorIndex + 1 : 0;
104
129
  for (let index = startIndex; index < orderedSessions.length; index += 1) {
105
- finalizeSessionIds.add(orderedSessions[index].id);
130
+ finalizeSessionIds.add(orderedSessions[index].reference.sessionId);
106
131
  }
107
132
  for (const changedId of changedIds) finalizeSessionIds.add(changedId);
108
133
  for (let index = 0; index <= cursorIndex; index += 1) {
109
134
  const session = orderedSessions[index];
110
- if (hasStaleSmartTags(session)) finalizeSessionIds.add(session.id);
135
+ if (hasStaleSessionTags(session)) finalizeSessionIds.add(session.reference.sessionId);
111
136
  }
112
137
  return { orderedSessions, finalizeSessionIds, cursorIndex };
113
138
  }
114
- function inheritSmartTags(sessions, previousSessions) {
115
- const previousById = new Map(previousSessions.map((session) => [session.id, session]));
116
- return sessions.map((session) => {
117
- if (Array.isArray(session.smart_tags)) return session;
118
- const previous = previousById.get(session.id);
119
- if (!previous || !Array.isArray(previous.smart_tags)) return session;
120
- return {
121
- ...session,
122
- smart_tags: previous.smart_tags,
123
- smart_tags_source_updated_at: previous.smart_tags_source_updated_at,
124
- smart_tags_classifier_revision: previous.smart_tags_classifier_revision
125
- };
126
- });
127
- }
128
139
  var TAG_SETTLE_MS = 6e4;
129
140
  var TAG_CHECKPOINT_SIZE = 32;
130
141
  var PROGRESS_INTERVAL_MS = 100;
@@ -161,7 +172,7 @@ function finalizeSessions(agent, sessions, onProgress, onCheckpoint, finalizeSes
161
172
  const ordered = sortSessions(attachMissingProjectIdentities(sessions));
162
173
  const now = Date.now();
163
174
  const settled = ordered.filter(
164
- (session) => (!finalizeSessionIds || finalizeSessionIds.has(session.id)) && isSettled(session, now)
175
+ (session) => (!finalizeSessionIds || finalizeSessionIds.has(session.reference.sessionId)) && isSettled(session, now)
165
176
  );
166
177
  if (settled.length === 0) return ordered;
167
178
  let lastReportedAt = -Infinity;
@@ -177,7 +188,9 @@ function finalizeSessions(agent, sessions, onProgress, onCheckpoint, finalizeSes
177
188
  });
178
189
  };
179
190
  reportProgress(0, settled.length);
180
- const sortIndexById = new Map(ordered.map((session, index) => [session.id, index]));
191
+ const sortIndexById = new Map(
192
+ ordered.map((session, index) => [session.reference.sessionId, index])
193
+ );
181
194
  const taggedById = /* @__PURE__ */ new Map();
182
195
  for (let start = 0; start < settled.length; start += TAG_CHECKPOINT_SIZE) {
183
196
  const batch = settled.slice(start, start + TAG_CHECKPOINT_SIZE);
@@ -186,17 +199,20 @@ function finalizeSessions(agent, sessions, onProgress, onCheckpoint, finalizeSes
186
199
  });
187
200
  if (taggedResult.timing) onTiming?.(taggedResult.timing);
188
201
  const taggedBatch = taggedResult.sessions;
189
- for (const session of taggedBatch) taggedById.set(session.id, session);
202
+ for (const session of taggedBatch) taggedById.set(session.reference.sessionId, session);
190
203
  onCheckpoint?.({
191
204
  stage: "finalizing",
192
205
  changes: taggedBatch.map((session) => ({
193
206
  session,
194
- sortIndex: sortIndexById.get(session.id) ?? 0
207
+ sortIndex: sortIndexById.get(session.reference.sessionId) ?? 0
195
208
  })),
196
- meta: buildAgentCacheMeta(agent, new Set(taggedBatch.map((session) => session.id)))
209
+ meta: buildAgentCacheMeta(
210
+ agent,
211
+ new Set(taggedBatch.map((session) => session.reference.sessionId))
212
+ )
197
213
  });
198
214
  }
199
- return ordered.map((session) => taggedById.get(session.id) ?? session);
215
+ return ordered.map((session) => taggedById.get(session.reference.sessionId) ?? session);
200
216
  }
201
217
  var workerBaseline = null;
202
218
  function baselineFor(data) {
@@ -230,7 +246,7 @@ function baselineFor(data) {
230
246
  if (workerBaseline.staged) {
231
247
  throw new Error(`Worker result ${workerBaseline.staged.requestId} is awaiting commit`);
232
248
  }
233
- workerBaseline.agent.setSessionMetaMap(new Map(Object.entries(workerBaseline.meta)));
249
+ workerBaseline.agent.restoreSessionCacheMeta(workerBaseline.meta);
234
250
  return workerBaseline;
235
251
  }
236
252
  async function run(data, progressEmitter) {
@@ -240,91 +256,53 @@ async function run(data, progressEmitter) {
240
256
  const previousSessions = baseline.sessions;
241
257
  const previousMeta = baseline.meta;
242
258
  const operation = data.operation;
243
- const sourceSynchronization = synchronizesSessionSources(operation);
244
259
  const backfill = isBackfillOperation(operation);
260
+ const scanPlan = planAgentScan(agent.sessionSourceAccess, scanIntentForOperation(operation));
245
261
  const durableCheckpoints = usesDurableCheckpoints(operation);
246
262
  const backfillCursor = backfill ? operation.cursor : void 0;
247
263
  appLogger.debug("scan.refresh_worker.started", {
248
264
  agent: data.agentName,
249
265
  operation: operation.kind,
250
266
  backfill_cursor: backfillCursor ?? void 0,
251
- changed_ids: operation.kind === "incremental-scan" ? operation.changedIds.length : 0,
252
267
  previous_sessions: previousSessions.length
253
268
  });
254
269
  const reportProgress = (progress) => {
255
270
  progressEmitter.push(progress, progress.phase ?? "scanning");
256
271
  };
257
- const isAvailable = agent.isAvailable();
258
- let sessions;
259
- let changedIds;
260
- let sourceFailures = [];
261
- let explicitRemovedSessionIds = [];
262
- let finalizeSessionIds;
272
+ if (!agent.isAvailable()) {
273
+ appLogger.warn("scan.refresh_worker.agent_unavailable", {
274
+ agent: data.agentName,
275
+ operation: operation.kind
276
+ });
277
+ throw new AgentUnavailableDuringScanError(data.agentName);
278
+ }
279
+ if (scanPlan.kind === "check-for-changes") {
280
+ throw new Error(`Change checks must run before dispatching Agent ${agent.name} to the worker`);
281
+ }
282
+ const execution = executeAgentScanPlan(
283
+ agent,
284
+ scanPlan,
285
+ { sessions: previousSessions, meta: previousMeta },
286
+ { ...data.scanOptions, onProgress: reportProgress }
287
+ );
288
+ let sessions = execution.sessions;
289
+ const changedIds = execution.changedSessionIds;
290
+ const sourceFailures = execution.sourceFailures;
291
+ const explicitRemovedSessionIds = execution.explicitRemovedSessionIds;
292
+ let finalizeSessionIds = execution.finalizeSessionIds === void 0 ? void 0 : new Set(execution.finalizeSessionIds);
263
293
  let backfillOrder;
264
294
  let backfillCursorIndex = -1;
265
- let sourceSynchronizationDetails;
266
- if (!isAvailable) {
267
- sessions = [];
268
- } else if (operation.kind === "recompute-derived") {
269
- sessions = previousSessions;
270
- } else if (sourceSynchronization) {
271
- if (!(agent instanceof FileSystemSessionSource)) {
272
- throw new Error(`Agent ${agent.name} does not support Session Source synchronization`);
273
- }
274
- const result = synchronizeSessionSources(
275
- agent,
276
- { sessions: previousSessions, meta: previousMeta },
277
- {
278
- kind: "refresh",
279
- scanOptions: { ...data.scanOptions, onProgress: reportProgress }
280
- }
281
- );
282
- sessions = result.sessions;
283
- changedIds = result.changedSessionIds;
284
- finalizeSessionIds = new Set(result.finalizeSessionIds);
285
- sourceSynchronizationDetails = {
286
- sourceCount: result.sourceCount,
287
- removedCount: result.removedSourceCount
288
- };
289
- sourceFailures = result.sourceFailures;
290
- explicitRemovedSessionIds = result.explicitRemovedSessionIds;
291
- } else if (operation.kind === "incremental-scan") {
292
- changedIds = operation.changedIds;
293
- sessions = inheritSmartTags(
294
- await Promise.resolve(
295
- agent.incrementalScan(previousSessions, operation.changedIds, void 0, {
296
- ...data.scanOptions,
297
- onProgress: reportProgress
298
- })
299
- ),
300
- previousSessions
301
- );
302
- } else if (agent instanceof FileSystemSessionSource) {
303
- const result = synchronizeSessionSources(
304
- agent,
305
- { sessions: previousSessions, meta: previousMeta },
306
- {
307
- kind: "reload",
308
- scanOptions: { ...data.scanOptions, onProgress: reportProgress }
309
- }
310
- );
311
- sessions = result.sessions;
312
- finalizeSessionIds = new Set(result.finalizeSessionIds);
313
- sourceFailures = result.sourceFailures;
314
- explicitRemovedSessionIds = result.explicitRemovedSessionIds;
315
- } else {
316
- sessions = inheritSmartTags(
317
- await Promise.resolve(
318
- agent.scan({
319
- ...data.scanOptions,
320
- onProgress: reportProgress
321
- })
322
- ),
323
- previousSessions
324
- );
325
- }
295
+ const sourceSynchronizationDetails = execution.sourceSynchronization ? {
296
+ sourceCount: execution.sourceSynchronization.sourceCount,
297
+ removedCount: execution.sourceSynchronization.removedSourceCount,
298
+ enumerationMs: execution.sourceSynchronization.timing.enumerationMs,
299
+ diffMs: execution.sourceSynchronization.timing.diffMs,
300
+ parseMs: execution.sourceSynchronization.timing.parseMs,
301
+ changedCount: execution.sourceSynchronization.timing.changedSourceCount,
302
+ processedCount: execution.sourceSynchronization.timing.processedSourceCount
303
+ } : void 0;
326
304
  sessions = attachMissingProjectIdentities(sessions);
327
- const completeness = data.scanOptions.from == null && data.scanOptions.to == null && sourceFailures.length === 0 ? "complete" : "partial";
305
+ const completeness = execution.completeness;
328
306
  if (durableCheckpoints) {
329
307
  const ordered = sortSessions(sessions);
330
308
  parentPort?.postMessage({
@@ -334,7 +312,10 @@ async function run(data, progressEmitter) {
334
312
  checkpoint: {
335
313
  stage: "scanned",
336
314
  sessions: ordered,
337
- meta: buildAgentCacheMeta(agent, new Set(ordered.map((session) => session.id))),
315
+ meta: buildAgentCacheMeta(
316
+ agent,
317
+ new Set(ordered.map((session) => session.reference.sessionId))
318
+ ),
338
319
  completeness
339
320
  }
340
321
  });
@@ -356,12 +337,17 @@ async function run(data, progressEmitter) {
356
337
  changed_ids: changedIds?.length ?? 0,
357
338
  source_count: sourceSynchronizationDetails?.sourceCount,
358
339
  removed_count: sourceSynchronizationDetails?.removedCount,
340
+ source_enumeration_ms: roundMilliseconds(sourceSynchronizationDetails?.enumerationMs ?? 0),
341
+ source_diff_ms: roundMilliseconds(sourceSynchronizationDetails?.diffMs ?? 0),
342
+ source_parse_ms: roundMilliseconds(sourceSynchronizationDetails?.parseMs ?? 0),
343
+ changed_sources: sourceSynchronizationDetails?.changedCount,
344
+ processed_sources: sourceSynchronizationDetails?.processedCount,
359
345
  failed_sources: sourceFailures.length,
360
346
  duration_ms: Math.round(scanDuration)
361
347
  });
362
348
  const finalizeStartedAt = performance.now();
363
349
  const finalizationTiming = createSessionFinalizationTiming();
364
- const backfillPositionById = backfillOrder ? new Map(backfillOrder.map((session, index) => [session.id, index])) : void 0;
350
+ const backfillPositionById = backfillOrder ? new Map(backfillOrder.map((session, index) => [session.reference.sessionId, index])) : void 0;
365
351
  sessions = finalizeSessions(
366
352
  agent,
367
353
  sessions,
@@ -371,14 +357,14 @@ async function run(data, progressEmitter) {
371
357
  if (checkpoint.stage === "finalizing" && backfillOrder && backfillPositionById) {
372
358
  let nextCursorIndex = backfillCursorIndex;
373
359
  for (const { session } of checkpoint.changes) {
374
- const index = backfillPositionById.get(session.id);
360
+ const index = backfillPositionById.get(session.reference.sessionId);
375
361
  if (index != null && index > nextCursorIndex) nextCursorIndex = index;
376
362
  }
377
363
  if (nextCursorIndex > backfillCursorIndex) {
378
364
  backfillCursorIndex = nextCursorIndex;
379
365
  nextCheckpoint = {
380
366
  ...checkpoint,
381
- backfillCursor: backfillOrder[nextCursorIndex]?.id
367
+ backfillCursor: backfillOrder[nextCursorIndex]?.reference.sessionId
382
368
  };
383
369
  }
384
370
  }
@@ -415,7 +401,7 @@ async function run(data, progressEmitter) {
415
401
  appLogger.debug("scan.refresh_worker.finalized", {
416
402
  agent: data.agentName,
417
403
  operation: operation.kind,
418
- backfill_cursor: backfillOrder?.[backfillCursorIndex]?.id,
404
+ backfill_cursor: backfillOrder?.[backfillCursorIndex]?.reference.sessionId,
419
405
  sessions: sessions.length,
420
406
  finalized_sessions: finalizationTiming.sessions,
421
407
  batches: finalizationTiming.batches,
@@ -436,14 +422,19 @@ async function run(data, progressEmitter) {
436
422
  duration_ms: roundMilliseconds(finalizationDuration),
437
423
  total_duration_ms: Math.round(performance.now() - startedAt)
438
424
  });
439
- const nextMeta = buildAgentCacheMeta(agent, new Set(sessions.map((session) => session.id)));
440
- const metaDiff = computeCacheMetaDiff(previousMeta, nextMeta);
441
- const diff = computeSessionDiff(
425
+ const nextMeta = buildAgentCacheMeta(
426
+ agent,
427
+ new Set(sessions.map((session) => session.reference.sessionId))
428
+ );
429
+ const delta = buildScanRefreshDelta({
442
430
  previousSessions,
443
431
  sessions,
444
- [...changedIds ?? [], ...Object.keys(metaDiff.changes), ...metaDiff.removedIds],
445
- sessionSignature
446
- );
432
+ previousMeta,
433
+ nextMeta,
434
+ changedIds,
435
+ completeness,
436
+ explicitRemovedSessionIds
437
+ });
447
438
  baseline.staged = {
448
439
  requestId: data.requestId,
449
440
  generation: baseline.generation,
@@ -455,10 +446,7 @@ async function run(data, progressEmitter) {
455
446
  type: "done",
456
447
  requestId: data.requestId,
457
448
  generation: baseline.generation,
458
- changes: diff.changes,
459
- removedSessionIds: diff.removedSessionIds,
460
- meta: metaDiff.changes,
461
- removedMetaIds: metaDiff.removedIds,
449
+ ...delta,
462
450
  sourceFailures,
463
451
  completeness,
464
452
  explicitRemovedSessionIds,
@@ -506,11 +494,13 @@ function commitBaseline(data) {
506
494
  workerBaseline.staged = null;
507
495
  }
508
496
  function postRequestError(data, error, startedAt) {
497
+ const errorCode = error instanceof AgentUnavailableDuringScanError ? error.code : void 0;
509
498
  parentPort?.postMessage({
510
499
  type: "error",
511
500
  requestId: data.requestId,
512
501
  generation: data.generation,
513
502
  error: error instanceof Error ? error.message : String(error),
503
+ ...errorCode ? { errorCode } : {},
514
504
  durationMs: performance.now() - startedAt
515
505
  });
516
506
  }
@@ -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 SessionHeadChange,\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 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: SessionHeadChange[];\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 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: SessionHeadChange[];\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 const isAvailable = agent.isAvailable();\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 (!isAvailable) {\n sessions = [];\n } else 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 parentPort?.postMessage({\n type: \"error\",\n requestId: data.requestId,\n generation: data.generation,\n error: error instanceof Error ? error.message : String(error),\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 } from \"./logging.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}\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 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(() => (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","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"]}