codesesh 1.0.3 → 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 (61) 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-WAKW5OPS.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-W4PZHL2C.js +2035 -0
  12. package/dist/chunk-W4PZHL2C.js.map +1 -0
  13. package/dist/chunk-YCUN52HA.js +8422 -0
  14. package/dist/chunk-YCUN52HA.js.map +1 -0
  15. package/dist/discovery-K3GLISI6.js +102 -0
  16. package/dist/discovery-K3GLISI6.js.map +1 -0
  17. package/dist/index.js +1899 -894
  18. package/dist/index.js.map +1 -1
  19. package/dist/project-identity-worker.js +4 -2
  20. package/dist/project-identity-worker.js.map +1 -1
  21. package/dist/scan-refresh-worker.js +117 -136
  22. package/dist/scan-refresh-worker.js.map +1 -1
  23. package/dist/search-index-worker.js +25 -9
  24. package/dist/search-index-worker.js.map +1 -1
  25. package/dist/smart-tag-worker.js +8 -5
  26. package/dist/smart-tag-worker.js.map +1 -1
  27. package/dist/web/assets/InteractiveReceipt-Dk50TBsH.js +1 -0
  28. package/dist/web/assets/OverviewScreen-5hvQVp4H.js +1 -0
  29. package/dist/web/assets/{PrismHighlighter-BZkkX0AU.js → PrismHighlighter-B1a2dPJO.js} +2 -2
  30. package/dist/web/assets/Projects-Cy_v2yep.js +1 -0
  31. package/dist/web/assets/SearchResultsPanel-DfheEwpz.js +1 -0
  32. package/dist/web/assets/SessionDetail-DRI8R3st.js +53 -0
  33. package/dist/web/assets/api-GP9UCedC.js +1 -0
  34. package/dist/web/assets/contract-xJyW5u7a.js +2 -0
  35. package/dist/web/assets/{index-3UfOiTBO.css → index-Bd-YkWkZ.css} +1 -1
  36. package/dist/web/assets/index-DEjvzumm.js +1410 -0
  37. package/dist/web/assets/panel-ND0J63d3.js +1 -0
  38. package/dist/web/assets/{session-indexes-BPhf1X2P.js → session-indexes-BsgjUoc1.js} +2 -2
  39. package/dist/web/assets/utils-C7BqyxxV.js +1 -0
  40. package/dist/web/index.html +7 -11
  41. package/package.json +4 -10
  42. package/dist/chunk-PSHZZITB.js +0 -17307
  43. package/dist/chunk-PSHZZITB.js.map +0 -1
  44. package/dist/chunk-WAKW5OPS.js.map +0 -1
  45. package/dist/dist-RHDY2EZX.js +0 -173
  46. package/dist/web/assets/ErrorBoundary-DIwwrdlw.js +0 -1
  47. package/dist/web/assets/InteractiveReceipt-DmNBDVms.js +0 -1
  48. package/dist/web/assets/OverviewScreen-B5JekBLC.js +0 -1
  49. package/dist/web/assets/Projects-Bj6ma2k2.js +0 -1
  50. package/dist/web/assets/SearchFilterBar-B9VrUbym.js +0 -1
  51. package/dist/web/assets/SearchResultsPanel-C1cuuOKq.js +0 -1
  52. package/dist/web/assets/SessionDetail-Dc2CQ3hH.js +0 -54
  53. package/dist/web/assets/SmartTagChips-ux6idUGJ.js +0 -1
  54. package/dist/web/assets/agents-BkRP_ww3.js +0 -1
  55. package/dist/web/assets/code-metrics-UYFsCC7E.js +0 -1
  56. package/dist/web/assets/contract-DXvltqJG.js +0 -1
  57. package/dist/web/assets/index-DBMiEd61.js +0 -1410
  58. package/dist/web/assets/panel-CLnL4kMN.js +0 -1
  59. package/dist/web/assets/session-title-DdtlxtlR.js +0 -1
  60. package/dist/web/assets/utils-BKqufGdv.js +0 -1
  61. /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-MBZ4VV4C.js";
3
+ import "./chunk-G4HRD3AR.js";
3
4
  import {
4
5
  computeIdentityProjection
5
- } from "./chunk-PSHZZITB.js";
6
+ } from "./chunk-3SXCTDD6.js";
7
+ import "./chunk-W4PZHL2C.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,30 @@
2
2
  import {
3
3
  AgentUnavailableDuringScanError
4
4
  } from "./chunk-RF3EEWPH.js";
5
+ import "./chunk-QH2HOXJH.js";
5
6
  import {
6
7
  appLogger
7
- } from "./chunk-WAKW5OPS.js";
8
+ } from "./chunk-G4HRD3AR.js";
8
9
  import {
9
- FileSystemSessionSource,
10
- SMART_TAG_CLASSIFIER_REVISION,
11
10
  attachMissingProjectIdentities,
12
11
  buildAgentCacheMeta,
13
- computeSessionDiff,
14
- createRegisteredAgents,
12
+ buildSessionPersistenceDiff,
15
13
  ensureSessionTagsSync,
16
- sessionSignature,
17
- sortSessions,
18
- synchronizePricingGeneration,
19
- synchronizeSessionSources
20
- } from "./chunk-PSHZZITB.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";
21
26
 
22
27
  // src/scan-refresh-worker.ts
23
28
  import { parentPort, workerData } from "worker_threads";
24
- import { isDeepStrictEqual } from "util";
25
29
 
26
30
  // src/monotonic-value-sampler.ts
27
31
  var MonotonicValueSampler = class {
@@ -72,62 +76,66 @@ var MonotonicValueSampler = class {
72
76
  }
73
77
  };
74
78
 
75
- // src/scan-refresh-operation.ts
76
- function synchronizesSessionSources(operation) {
77
- 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
+ };
78
101
  }
102
+
103
+ // src/scan-refresh-operation.ts
79
104
  function isBackfillOperation(operation) {
80
- return operation.kind === "full-backfill" || operation.kind === "source-backfill";
105
+ return operation.kind === "backfill";
81
106
  }
82
107
  function usesDurableCheckpoints(operation) {
83
108
  return "checkpoint" in operation && operation.checkpoint === "durable";
84
109
  }
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);
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";
95
120
  }
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
121
  }
122
+
123
+ // src/scan-refresh-worker.ts
102
124
  function selectBackfillSessions(sessions, changedIds, cursor) {
103
125
  const orderedSessions = sortSessions(sessions);
104
- const cursorIndex = cursor ? orderedSessions.findIndex((session) => session.id === cursor) : -1;
126
+ const cursorIndex = cursor ? orderedSessions.findIndex((session) => session.reference.sessionId === cursor) : -1;
105
127
  const finalizeSessionIds = /* @__PURE__ */ new Set();
106
128
  const startIndex = cursorIndex >= 0 ? cursorIndex + 1 : 0;
107
129
  for (let index = startIndex; index < orderedSessions.length; index += 1) {
108
- finalizeSessionIds.add(orderedSessions[index].id);
130
+ finalizeSessionIds.add(orderedSessions[index].reference.sessionId);
109
131
  }
110
132
  for (const changedId of changedIds) finalizeSessionIds.add(changedId);
111
133
  for (let index = 0; index <= cursorIndex; index += 1) {
112
134
  const session = orderedSessions[index];
113
- if (hasStaleSmartTags(session)) finalizeSessionIds.add(session.id);
135
+ if (hasStaleSessionTags(session)) finalizeSessionIds.add(session.reference.sessionId);
114
136
  }
115
137
  return { orderedSessions, finalizeSessionIds, cursorIndex };
116
138
  }
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
139
  var TAG_SETTLE_MS = 6e4;
132
140
  var TAG_CHECKPOINT_SIZE = 32;
133
141
  var PROGRESS_INTERVAL_MS = 100;
@@ -164,7 +172,7 @@ function finalizeSessions(agent, sessions, onProgress, onCheckpoint, finalizeSes
164
172
  const ordered = sortSessions(attachMissingProjectIdentities(sessions));
165
173
  const now = Date.now();
166
174
  const settled = ordered.filter(
167
- (session) => (!finalizeSessionIds || finalizeSessionIds.has(session.id)) && isSettled(session, now)
175
+ (session) => (!finalizeSessionIds || finalizeSessionIds.has(session.reference.sessionId)) && isSettled(session, now)
168
176
  );
169
177
  if (settled.length === 0) return ordered;
170
178
  let lastReportedAt = -Infinity;
@@ -180,7 +188,9 @@ function finalizeSessions(agent, sessions, onProgress, onCheckpoint, finalizeSes
180
188
  });
181
189
  };
182
190
  reportProgress(0, settled.length);
183
- 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
+ );
184
194
  const taggedById = /* @__PURE__ */ new Map();
185
195
  for (let start = 0; start < settled.length; start += TAG_CHECKPOINT_SIZE) {
186
196
  const batch = settled.slice(start, start + TAG_CHECKPOINT_SIZE);
@@ -189,17 +199,20 @@ function finalizeSessions(agent, sessions, onProgress, onCheckpoint, finalizeSes
189
199
  });
190
200
  if (taggedResult.timing) onTiming?.(taggedResult.timing);
191
201
  const taggedBatch = taggedResult.sessions;
192
- for (const session of taggedBatch) taggedById.set(session.id, session);
202
+ for (const session of taggedBatch) taggedById.set(session.reference.sessionId, session);
193
203
  onCheckpoint?.({
194
204
  stage: "finalizing",
195
205
  changes: taggedBatch.map((session) => ({
196
206
  session,
197
- sortIndex: sortIndexById.get(session.id) ?? 0
207
+ sortIndex: sortIndexById.get(session.reference.sessionId) ?? 0
198
208
  })),
199
- 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
+ )
200
213
  });
201
214
  }
202
- return ordered.map((session) => taggedById.get(session.id) ?? session);
215
+ return ordered.map((session) => taggedById.get(session.reference.sessionId) ?? session);
203
216
  }
204
217
  var workerBaseline = null;
205
218
  function baselineFor(data) {
@@ -233,7 +246,7 @@ function baselineFor(data) {
233
246
  if (workerBaseline.staged) {
234
247
  throw new Error(`Worker result ${workerBaseline.staged.requestId} is awaiting commit`);
235
248
  }
236
- workerBaseline.agent.setSessionMetaMap(new Map(Object.entries(workerBaseline.meta)));
249
+ workerBaseline.agent.restoreSessionCacheMeta(workerBaseline.meta);
237
250
  return workerBaseline;
238
251
  }
239
252
  async function run(data, progressEmitter) {
@@ -243,15 +256,14 @@ async function run(data, progressEmitter) {
243
256
  const previousSessions = baseline.sessions;
244
257
  const previousMeta = baseline.meta;
245
258
  const operation = data.operation;
246
- const sourceSynchronization = synchronizesSessionSources(operation);
247
259
  const backfill = isBackfillOperation(operation);
260
+ const scanPlan = planAgentScan(agent.sessionSourceAccess, scanIntentForOperation(operation));
248
261
  const durableCheckpoints = usesDurableCheckpoints(operation);
249
262
  const backfillCursor = backfill ? operation.cursor : void 0;
250
263
  appLogger.debug("scan.refresh_worker.started", {
251
264
  agent: data.agentName,
252
265
  operation: operation.kind,
253
266
  backfill_cursor: backfillCursor ?? void 0,
254
- changed_ids: operation.kind === "incremental-scan" ? operation.changedIds.length : 0,
255
267
  previous_sessions: previousSessions.length
256
268
  });
257
269
  const reportProgress = (progress) => {
@@ -264,74 +276,33 @@ async function run(data, progressEmitter) {
264
276
  });
265
277
  throw new AgentUnavailableDuringScanError(data.agentName);
266
278
  }
267
- let sessions;
268
- let changedIds;
269
- let sourceFailures = [];
270
- let explicitRemovedSessionIds = [];
271
- let finalizeSessionIds;
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);
272
293
  let backfillOrder;
273
294
  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
- }
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;
333
304
  sessions = attachMissingProjectIdentities(sessions);
334
- const completeness = data.scanOptions.from == null && data.scanOptions.to == null && sourceFailures.length === 0 ? "complete" : "partial";
305
+ const completeness = execution.completeness;
335
306
  if (durableCheckpoints) {
336
307
  const ordered = sortSessions(sessions);
337
308
  parentPort?.postMessage({
@@ -341,7 +312,10 @@ async function run(data, progressEmitter) {
341
312
  checkpoint: {
342
313
  stage: "scanned",
343
314
  sessions: ordered,
344
- 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
+ ),
345
319
  completeness
346
320
  }
347
321
  });
@@ -363,12 +337,17 @@ async function run(data, progressEmitter) {
363
337
  changed_ids: changedIds?.length ?? 0,
364
338
  source_count: sourceSynchronizationDetails?.sourceCount,
365
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,
366
345
  failed_sources: sourceFailures.length,
367
346
  duration_ms: Math.round(scanDuration)
368
347
  });
369
348
  const finalizeStartedAt = performance.now();
370
349
  const finalizationTiming = createSessionFinalizationTiming();
371
- 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;
372
351
  sessions = finalizeSessions(
373
352
  agent,
374
353
  sessions,
@@ -378,14 +357,14 @@ async function run(data, progressEmitter) {
378
357
  if (checkpoint.stage === "finalizing" && backfillOrder && backfillPositionById) {
379
358
  let nextCursorIndex = backfillCursorIndex;
380
359
  for (const { session } of checkpoint.changes) {
381
- const index = backfillPositionById.get(session.id);
360
+ const index = backfillPositionById.get(session.reference.sessionId);
382
361
  if (index != null && index > nextCursorIndex) nextCursorIndex = index;
383
362
  }
384
363
  if (nextCursorIndex > backfillCursorIndex) {
385
364
  backfillCursorIndex = nextCursorIndex;
386
365
  nextCheckpoint = {
387
366
  ...checkpoint,
388
- backfillCursor: backfillOrder[nextCursorIndex]?.id
367
+ backfillCursor: backfillOrder[nextCursorIndex]?.reference.sessionId
389
368
  };
390
369
  }
391
370
  }
@@ -422,7 +401,7 @@ async function run(data, progressEmitter) {
422
401
  appLogger.debug("scan.refresh_worker.finalized", {
423
402
  agent: data.agentName,
424
403
  operation: operation.kind,
425
- backfill_cursor: backfillOrder?.[backfillCursorIndex]?.id,
404
+ backfill_cursor: backfillOrder?.[backfillCursorIndex]?.reference.sessionId,
426
405
  sessions: sessions.length,
427
406
  finalized_sessions: finalizationTiming.sessions,
428
407
  batches: finalizationTiming.batches,
@@ -443,14 +422,19 @@ async function run(data, progressEmitter) {
443
422
  duration_ms: roundMilliseconds(finalizationDuration),
444
423
  total_duration_ms: Math.round(performance.now() - startedAt)
445
424
  });
446
- const nextMeta = buildAgentCacheMeta(agent, new Set(sessions.map((session) => session.id)));
447
- const metaDiff = computeCacheMetaDiff(previousMeta, nextMeta);
448
- const diff = computeSessionDiff(
425
+ const nextMeta = buildAgentCacheMeta(
426
+ agent,
427
+ new Set(sessions.map((session) => session.reference.sessionId))
428
+ );
429
+ const delta = buildScanRefreshDelta({
449
430
  previousSessions,
450
431
  sessions,
451
- [...changedIds ?? [], ...Object.keys(metaDiff.changes), ...metaDiff.removedIds],
452
- sessionSignature
453
- );
432
+ previousMeta,
433
+ nextMeta,
434
+ changedIds,
435
+ completeness,
436
+ explicitRemovedSessionIds
437
+ });
454
438
  baseline.staged = {
455
439
  requestId: data.requestId,
456
440
  generation: baseline.generation,
@@ -462,10 +446,7 @@ async function run(data, progressEmitter) {
462
446
  type: "done",
463
447
  requestId: data.requestId,
464
448
  generation: baseline.generation,
465
- changes: diff.changes,
466
- removedSessionIds: diff.removedSessionIds,
467
- meta: metaDiff.changes,
468
- removedMetaIds: metaDiff.removedIds,
449
+ ...delta,
469
450
  sourceFailures,
470
451
  completeness,
471
452
  explicitRemovedSessionIds,
@@ -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 } 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"]}