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.
- package/README.md +18 -10
- package/dist/chunk-3SXCTDD6.js +326 -0
- package/dist/chunk-3SXCTDD6.js.map +1 -0
- package/dist/chunk-BYB77UAJ.js +6054 -0
- package/dist/chunk-BYB77UAJ.js.map +1 -0
- package/dist/{chunk-WAKW5OPS.js → chunk-G4HRD3AR.js} +13 -8
- package/dist/chunk-G4HRD3AR.js.map +1 -0
- package/dist/chunk-MBZ4VV4C.js +670 -0
- package/dist/chunk-MBZ4VV4C.js.map +1 -0
- package/dist/chunk-QH2HOXJH.js +2 -0
- package/dist/chunk-W4PZHL2C.js +2035 -0
- package/dist/chunk-W4PZHL2C.js.map +1 -0
- package/dist/chunk-YCUN52HA.js +8422 -0
- package/dist/chunk-YCUN52HA.js.map +1 -0
- package/dist/discovery-K3GLISI6.js +102 -0
- package/dist/discovery-K3GLISI6.js.map +1 -0
- package/dist/index.js +1899 -894
- package/dist/index.js.map +1 -1
- package/dist/project-identity-worker.js +4 -2
- package/dist/project-identity-worker.js.map +1 -1
- package/dist/scan-refresh-worker.js +117 -136
- package/dist/scan-refresh-worker.js.map +1 -1
- package/dist/search-index-worker.js +25 -9
- package/dist/search-index-worker.js.map +1 -1
- package/dist/smart-tag-worker.js +8 -5
- package/dist/smart-tag-worker.js.map +1 -1
- package/dist/web/assets/InteractiveReceipt-Dk50TBsH.js +1 -0
- package/dist/web/assets/OverviewScreen-5hvQVp4H.js +1 -0
- package/dist/web/assets/{PrismHighlighter-BZkkX0AU.js → PrismHighlighter-B1a2dPJO.js} +2 -2
- package/dist/web/assets/Projects-Cy_v2yep.js +1 -0
- package/dist/web/assets/SearchResultsPanel-DfheEwpz.js +1 -0
- package/dist/web/assets/SessionDetail-DRI8R3st.js +53 -0
- package/dist/web/assets/api-GP9UCedC.js +1 -0
- package/dist/web/assets/contract-xJyW5u7a.js +2 -0
- package/dist/web/assets/{index-3UfOiTBO.css → index-Bd-YkWkZ.css} +1 -1
- package/dist/web/assets/index-DEjvzumm.js +1410 -0
- package/dist/web/assets/panel-ND0J63d3.js +1 -0
- package/dist/web/assets/{session-indexes-BPhf1X2P.js → session-indexes-BsgjUoc1.js} +2 -2
- package/dist/web/assets/utils-C7BqyxxV.js +1 -0
- package/dist/web/index.html +7 -11
- package/package.json +4 -10
- package/dist/chunk-PSHZZITB.js +0 -17307
- package/dist/chunk-PSHZZITB.js.map +0 -1
- package/dist/chunk-WAKW5OPS.js.map +0 -1
- package/dist/dist-RHDY2EZX.js +0 -173
- package/dist/web/assets/ErrorBoundary-DIwwrdlw.js +0 -1
- package/dist/web/assets/InteractiveReceipt-DmNBDVms.js +0 -1
- package/dist/web/assets/OverviewScreen-B5JekBLC.js +0 -1
- package/dist/web/assets/Projects-Bj6ma2k2.js +0 -1
- package/dist/web/assets/SearchFilterBar-B9VrUbym.js +0 -1
- package/dist/web/assets/SearchResultsPanel-C1cuuOKq.js +0 -1
- package/dist/web/assets/SessionDetail-Dc2CQ3hH.js +0 -54
- package/dist/web/assets/SmartTagChips-ux6idUGJ.js +0 -1
- package/dist/web/assets/agents-BkRP_ww3.js +0 -1
- package/dist/web/assets/code-metrics-UYFsCC7E.js +0 -1
- package/dist/web/assets/contract-DXvltqJG.js +0 -1
- package/dist/web/assets/index-DBMiEd61.js +0 -1410
- package/dist/web/assets/panel-CLnL4kMN.js +0 -1
- package/dist/web/assets/session-title-DdtlxtlR.js +0 -1
- package/dist/web/assets/utils-BKqufGdv.js +0 -1
- /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-
|
|
2
|
+
import "./chunk-MBZ4VV4C.js";
|
|
3
|
+
import "./chunk-G4HRD3AR.js";
|
|
3
4
|
import {
|
|
4
5
|
computeIdentityProjection
|
|
5
|
-
} from "./chunk-
|
|
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 {
|
|
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-
|
|
8
|
+
} from "./chunk-G4HRD3AR.js";
|
|
8
9
|
import {
|
|
9
|
-
FileSystemSessionSource,
|
|
10
|
-
SMART_TAG_CLASSIFIER_REVISION,
|
|
11
10
|
attachMissingProjectIdentities,
|
|
12
11
|
buildAgentCacheMeta,
|
|
13
|
-
|
|
14
|
-
createRegisteredAgents,
|
|
12
|
+
buildSessionPersistenceDiff,
|
|
15
13
|
ensureSessionTagsSync,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
} from "./chunk-
|
|
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-
|
|
76
|
-
|
|
77
|
-
|
|
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 === "
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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.
|
|
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].
|
|
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 (
|
|
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.
|
|
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(
|
|
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.
|
|
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.
|
|
207
|
+
sortIndex: sortIndexById.get(session.reference.sessionId) ?? 0
|
|
198
208
|
})),
|
|
199
|
-
meta: buildAgentCacheMeta(
|
|
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.
|
|
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.
|
|
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
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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 =
|
|
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(
|
|
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.
|
|
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.
|
|
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]?.
|
|
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]?.
|
|
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(
|
|
447
|
-
|
|
448
|
-
|
|
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
|
-
|
|
452
|
-
|
|
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
|
-
|
|
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"]}
|