codesesh 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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-PROMURPM.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-RF3EEWPH.js +17 -0
- package/dist/chunk-RF3EEWPH.js.map +1 -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 +3016 -1392
- package/dist/index.js.map +1 -1
- package/dist/project-identity-worker.js +29 -0
- package/dist/project-identity-worker.js.map +1 -0
- package/dist/scan-refresh-worker.js +129 -139
- package/dist/scan-refresh-worker.js.map +1 -1
- package/dist/search-index-worker.js +39 -13
- 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-Bd-YkWkZ.css +1 -0
- package/dist/web/assets/index-DEjvzumm.js +1410 -0
- package/dist/web/assets/panel-ND0J63d3.js +1 -0
- package/dist/web/assets/{session-indexes-0oT5HSS5.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-PROMURPM.js.map +0 -1
- package/dist/chunk-VAUC2W7I.js +0 -16119
- package/dist/chunk-VAUC2W7I.js.map +0 -1
- package/dist/dist-6QTGTYZT.js +0 -175
- package/dist/web/assets/ErrorBoundary-D11tWzfn.js +0 -1
- package/dist/web/assets/InteractiveReceipt-DYGyHeZd.js +0 -1
- package/dist/web/assets/OverviewScreen-DriPmCam.js +0 -1
- package/dist/web/assets/Projects-BPDIcUBK.js +0 -1
- package/dist/web/assets/SearchFilterBar-Bx73B5e9.js +0 -1
- package/dist/web/assets/SearchResultsPanel-A6_3TPhW.js +0 -1
- package/dist/web/assets/SessionDetail-BnpvDwtH.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-V6QuD0UY.js +0 -1
- package/dist/web/assets/index-99ZxpV2y.js +0 -1410
- package/dist/web/assets/index-B2RqUgZ5.css +0 -1
- package/dist/web/assets/panel-C-gc79Gz.js +0 -1
- package/dist/web/assets/session-title-DdtlxtlR.js +0 -1
- package/dist/web/assets/utils-DgUgu15E.js +0 -1
- /package/dist/{dist-6QTGTYZT.js.map → chunk-QH2HOXJH.js.map} +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./chunk-MBZ4VV4C.js";
|
|
3
|
+
import "./chunk-G4HRD3AR.js";
|
|
4
|
+
import {
|
|
5
|
+
computeIdentityProjection
|
|
6
|
+
} from "./chunk-3SXCTDD6.js";
|
|
7
|
+
import "./chunk-W4PZHL2C.js";
|
|
8
|
+
|
|
9
|
+
// src/project-identity-worker.ts
|
|
10
|
+
import { parentPort } from "worker_threads";
|
|
11
|
+
function resolveIdentity(request) {
|
|
12
|
+
try {
|
|
13
|
+
parentPort?.postMessage({
|
|
14
|
+
type: "resolved",
|
|
15
|
+
requestId: request.requestId,
|
|
16
|
+
projection: computeIdentityProjection(request.cwd)
|
|
17
|
+
});
|
|
18
|
+
} catch (error) {
|
|
19
|
+
parentPort?.postMessage({
|
|
20
|
+
type: "failed",
|
|
21
|
+
requestId: request.requestId,
|
|
22
|
+
error: error instanceof Error ? error.message : String(error)
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
parentPort?.on("message", (message) => {
|
|
27
|
+
if (message.type === "resolve") resolveIdentity(message);
|
|
28
|
+
});
|
|
29
|
+
//# sourceMappingURL=project-identity-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/project-identity-worker.ts"],"sourcesContent":["import \"./diagnostics-bridge.js\";\nimport { parentPort } from \"node:worker_threads\";\nimport {\n computeIdentityProjection,\n type ProjectIdentityProjection,\n} from \"@codesesh/core/runtime/projects\";\n\nexport interface ProjectIdentityWorkerRequest {\n type: \"resolve\";\n requestId: number;\n cwd: string;\n}\n\nexport type ProjectIdentityWorkerMessage =\n | {\n type: \"resolved\";\n requestId: number;\n projection: ProjectIdentityProjection;\n }\n | {\n type: \"failed\";\n requestId: number;\n error: string;\n };\n\nfunction resolveIdentity(request: ProjectIdentityWorkerRequest): void {\n try {\n parentPort?.postMessage({\n type: \"resolved\",\n requestId: request.requestId,\n projection: computeIdentityProjection(request.cwd),\n } satisfies ProjectIdentityWorkerMessage);\n } catch (error) {\n parentPort?.postMessage({\n type: \"failed\",\n requestId: request.requestId,\n error: error instanceof Error ? error.message : String(error),\n } satisfies ProjectIdentityWorkerMessage);\n }\n}\n\nparentPort?.on(\"message\", (message: ProjectIdentityWorkerRequest) => {\n if (message.type === \"resolve\") resolveIdentity(message);\n});\n"],"mappings":";;;;;;;;;AACA,SAAS,kBAAkB;AAwB3B,SAAS,gBAAgB,SAA6C;AACpE,MAAI;AACF,gBAAY,YAAY;AAAA,MACtB,MAAM;AAAA,MACN,WAAW,QAAQ;AAAA,MACnB,YAAY,0BAA0B,QAAQ,GAAG;AAAA,IACnD,CAAwC;AAAA,EAC1C,SAAS,OAAO;AACd,gBAAY,YAAY;AAAA,MACtB,MAAM;AAAA,MACN,WAAW,QAAQ;AAAA,MACnB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D,CAAwC;AAAA,EAC1C;AACF;AAEA,YAAY,GAAG,WAAW,CAAC,YAA0C;AACnE,MAAI,QAAQ,SAAS,UAAW,iBAAgB,OAAO;AACzD,CAAC;","names":[]}
|
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
AgentUnavailableDuringScanError
|
|
4
|
+
} from "./chunk-RF3EEWPH.js";
|
|
5
|
+
import "./chunk-QH2HOXJH.js";
|
|
2
6
|
import {
|
|
3
7
|
appLogger
|
|
4
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-G4HRD3AR.js";
|
|
5
9
|
import {
|
|
6
|
-
FileSystemSessionSource,
|
|
7
|
-
SMART_TAG_CLASSIFIER_REVISION,
|
|
8
10
|
attachMissingProjectIdentities,
|
|
9
11
|
buildAgentCacheMeta,
|
|
10
|
-
|
|
11
|
-
createRegisteredAgents,
|
|
12
|
+
buildSessionPersistenceDiff,
|
|
12
13
|
ensureSessionTagsSync,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} 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";
|
|
18
26
|
|
|
19
27
|
// src/scan-refresh-worker.ts
|
|
20
28
|
import { parentPort, workerData } from "worker_threads";
|
|
21
|
-
import { isDeepStrictEqual } from "util";
|
|
22
29
|
|
|
23
30
|
// src/monotonic-value-sampler.ts
|
|
24
31
|
var MonotonicValueSampler = class {
|
|
@@ -69,62 +76,66 @@ var MonotonicValueSampler = class {
|
|
|
69
76
|
}
|
|
70
77
|
};
|
|
71
78
|
|
|
72
|
-
// src/scan-refresh-
|
|
73
|
-
|
|
74
|
-
|
|
79
|
+
// src/scan-refresh-delta.ts
|
|
80
|
+
import { isDeepStrictEqual } from "util";
|
|
81
|
+
function buildScanRefreshDelta(input) {
|
|
82
|
+
const meta = {};
|
|
83
|
+
const removedMetaIds = [];
|
|
84
|
+
for (const [id, value] of Object.entries(input.nextMeta)) {
|
|
85
|
+
if (!isDeepStrictEqual(input.previousMeta[id], value)) meta[id] = value;
|
|
86
|
+
}
|
|
87
|
+
for (const id of Object.keys(input.previousMeta)) {
|
|
88
|
+
if (!Object.hasOwn(input.nextMeta, id)) removedMetaIds.push(id);
|
|
89
|
+
}
|
|
90
|
+
const diff = buildSessionPersistenceDiff(input.previousSessions, input.sessions, {
|
|
91
|
+
candidateChangedIds: [...input.changedIds ?? [], ...Object.keys(meta), ...removedMetaIds],
|
|
92
|
+
completeness: input.completeness,
|
|
93
|
+
explicitRemovedSessionIds: input.explicitRemovedSessionIds
|
|
94
|
+
});
|
|
95
|
+
return {
|
|
96
|
+
changes: diff.changedSessions,
|
|
97
|
+
removedSessionIds: diff.removedSessionIds,
|
|
98
|
+
meta,
|
|
99
|
+
removedMetaIds
|
|
100
|
+
};
|
|
75
101
|
}
|
|
102
|
+
|
|
103
|
+
// src/scan-refresh-operation.ts
|
|
76
104
|
function isBackfillOperation(operation) {
|
|
77
|
-
return operation.kind === "
|
|
105
|
+
return operation.kind === "backfill";
|
|
78
106
|
}
|
|
79
107
|
function usesDurableCheckpoints(operation) {
|
|
80
108
|
return "checkpoint" in operation && operation.checkpoint === "durable";
|
|
81
109
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
110
|
+
function scanIntentForOperation(operation) {
|
|
111
|
+
switch (operation.kind) {
|
|
112
|
+
case "full-scan":
|
|
113
|
+
return "reload";
|
|
114
|
+
case "source-refresh":
|
|
115
|
+
return "refresh";
|
|
116
|
+
case "recompute-derived":
|
|
117
|
+
return "recompute-derived";
|
|
118
|
+
case "backfill":
|
|
119
|
+
return "backfill";
|
|
92
120
|
}
|
|
93
|
-
return { changes, removedIds };
|
|
94
|
-
}
|
|
95
|
-
function hasStaleSmartTags(session) {
|
|
96
|
-
const sourceUpdatedAt = session.time_updated ?? session.time_created;
|
|
97
|
-
return !Array.isArray(session.smart_tags) || session.smart_tags_source_updated_at !== sourceUpdatedAt || session.smart_tags_classifier_revision !== SMART_TAG_CLASSIFIER_REVISION;
|
|
98
121
|
}
|
|
122
|
+
|
|
123
|
+
// src/scan-refresh-worker.ts
|
|
99
124
|
function selectBackfillSessions(sessions, changedIds, cursor) {
|
|
100
125
|
const orderedSessions = sortSessions(sessions);
|
|
101
|
-
const cursorIndex = cursor ? orderedSessions.findIndex((session) => session.
|
|
126
|
+
const cursorIndex = cursor ? orderedSessions.findIndex((session) => session.reference.sessionId === cursor) : -1;
|
|
102
127
|
const finalizeSessionIds = /* @__PURE__ */ new Set();
|
|
103
128
|
const startIndex = cursorIndex >= 0 ? cursorIndex + 1 : 0;
|
|
104
129
|
for (let index = startIndex; index < orderedSessions.length; index += 1) {
|
|
105
|
-
finalizeSessionIds.add(orderedSessions[index].
|
|
130
|
+
finalizeSessionIds.add(orderedSessions[index].reference.sessionId);
|
|
106
131
|
}
|
|
107
132
|
for (const changedId of changedIds) finalizeSessionIds.add(changedId);
|
|
108
133
|
for (let index = 0; index <= cursorIndex; index += 1) {
|
|
109
134
|
const session = orderedSessions[index];
|
|
110
|
-
if (
|
|
135
|
+
if (hasStaleSessionTags(session)) finalizeSessionIds.add(session.reference.sessionId);
|
|
111
136
|
}
|
|
112
137
|
return { orderedSessions, finalizeSessionIds, cursorIndex };
|
|
113
138
|
}
|
|
114
|
-
function inheritSmartTags(sessions, previousSessions) {
|
|
115
|
-
const previousById = new Map(previousSessions.map((session) => [session.id, session]));
|
|
116
|
-
return sessions.map((session) => {
|
|
117
|
-
if (Array.isArray(session.smart_tags)) return session;
|
|
118
|
-
const previous = previousById.get(session.id);
|
|
119
|
-
if (!previous || !Array.isArray(previous.smart_tags)) return session;
|
|
120
|
-
return {
|
|
121
|
-
...session,
|
|
122
|
-
smart_tags: previous.smart_tags,
|
|
123
|
-
smart_tags_source_updated_at: previous.smart_tags_source_updated_at,
|
|
124
|
-
smart_tags_classifier_revision: previous.smart_tags_classifier_revision
|
|
125
|
-
};
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
139
|
var TAG_SETTLE_MS = 6e4;
|
|
129
140
|
var TAG_CHECKPOINT_SIZE = 32;
|
|
130
141
|
var PROGRESS_INTERVAL_MS = 100;
|
|
@@ -161,7 +172,7 @@ function finalizeSessions(agent, sessions, onProgress, onCheckpoint, finalizeSes
|
|
|
161
172
|
const ordered = sortSessions(attachMissingProjectIdentities(sessions));
|
|
162
173
|
const now = Date.now();
|
|
163
174
|
const settled = ordered.filter(
|
|
164
|
-
(session) => (!finalizeSessionIds || finalizeSessionIds.has(session.
|
|
175
|
+
(session) => (!finalizeSessionIds || finalizeSessionIds.has(session.reference.sessionId)) && isSettled(session, now)
|
|
165
176
|
);
|
|
166
177
|
if (settled.length === 0) return ordered;
|
|
167
178
|
let lastReportedAt = -Infinity;
|
|
@@ -177,7 +188,9 @@ function finalizeSessions(agent, sessions, onProgress, onCheckpoint, finalizeSes
|
|
|
177
188
|
});
|
|
178
189
|
};
|
|
179
190
|
reportProgress(0, settled.length);
|
|
180
|
-
const sortIndexById = new Map(
|
|
191
|
+
const sortIndexById = new Map(
|
|
192
|
+
ordered.map((session, index) => [session.reference.sessionId, index])
|
|
193
|
+
);
|
|
181
194
|
const taggedById = /* @__PURE__ */ new Map();
|
|
182
195
|
for (let start = 0; start < settled.length; start += TAG_CHECKPOINT_SIZE) {
|
|
183
196
|
const batch = settled.slice(start, start + TAG_CHECKPOINT_SIZE);
|
|
@@ -186,17 +199,20 @@ function finalizeSessions(agent, sessions, onProgress, onCheckpoint, finalizeSes
|
|
|
186
199
|
});
|
|
187
200
|
if (taggedResult.timing) onTiming?.(taggedResult.timing);
|
|
188
201
|
const taggedBatch = taggedResult.sessions;
|
|
189
|
-
for (const session of taggedBatch) taggedById.set(session.
|
|
202
|
+
for (const session of taggedBatch) taggedById.set(session.reference.sessionId, session);
|
|
190
203
|
onCheckpoint?.({
|
|
191
204
|
stage: "finalizing",
|
|
192
205
|
changes: taggedBatch.map((session) => ({
|
|
193
206
|
session,
|
|
194
|
-
sortIndex: sortIndexById.get(session.
|
|
207
|
+
sortIndex: sortIndexById.get(session.reference.sessionId) ?? 0
|
|
195
208
|
})),
|
|
196
|
-
meta: buildAgentCacheMeta(
|
|
209
|
+
meta: buildAgentCacheMeta(
|
|
210
|
+
agent,
|
|
211
|
+
new Set(taggedBatch.map((session) => session.reference.sessionId))
|
|
212
|
+
)
|
|
197
213
|
});
|
|
198
214
|
}
|
|
199
|
-
return ordered.map((session) => taggedById.get(session.
|
|
215
|
+
return ordered.map((session) => taggedById.get(session.reference.sessionId) ?? session);
|
|
200
216
|
}
|
|
201
217
|
var workerBaseline = null;
|
|
202
218
|
function baselineFor(data) {
|
|
@@ -230,7 +246,7 @@ function baselineFor(data) {
|
|
|
230
246
|
if (workerBaseline.staged) {
|
|
231
247
|
throw new Error(`Worker result ${workerBaseline.staged.requestId} is awaiting commit`);
|
|
232
248
|
}
|
|
233
|
-
workerBaseline.agent.
|
|
249
|
+
workerBaseline.agent.restoreSessionCacheMeta(workerBaseline.meta);
|
|
234
250
|
return workerBaseline;
|
|
235
251
|
}
|
|
236
252
|
async function run(data, progressEmitter) {
|
|
@@ -240,91 +256,53 @@ async function run(data, progressEmitter) {
|
|
|
240
256
|
const previousSessions = baseline.sessions;
|
|
241
257
|
const previousMeta = baseline.meta;
|
|
242
258
|
const operation = data.operation;
|
|
243
|
-
const sourceSynchronization = synchronizesSessionSources(operation);
|
|
244
259
|
const backfill = isBackfillOperation(operation);
|
|
260
|
+
const scanPlan = planAgentScan(agent.sessionSourceAccess, scanIntentForOperation(operation));
|
|
245
261
|
const durableCheckpoints = usesDurableCheckpoints(operation);
|
|
246
262
|
const backfillCursor = backfill ? operation.cursor : void 0;
|
|
247
263
|
appLogger.debug("scan.refresh_worker.started", {
|
|
248
264
|
agent: data.agentName,
|
|
249
265
|
operation: operation.kind,
|
|
250
266
|
backfill_cursor: backfillCursor ?? void 0,
|
|
251
|
-
changed_ids: operation.kind === "incremental-scan" ? operation.changedIds.length : 0,
|
|
252
267
|
previous_sessions: previousSessions.length
|
|
253
268
|
});
|
|
254
269
|
const reportProgress = (progress) => {
|
|
255
270
|
progressEmitter.push(progress, progress.phase ?? "scanning");
|
|
256
271
|
};
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
272
|
+
if (!agent.isAvailable()) {
|
|
273
|
+
appLogger.warn("scan.refresh_worker.agent_unavailable", {
|
|
274
|
+
agent: data.agentName,
|
|
275
|
+
operation: operation.kind
|
|
276
|
+
});
|
|
277
|
+
throw new AgentUnavailableDuringScanError(data.agentName);
|
|
278
|
+
}
|
|
279
|
+
if (scanPlan.kind === "check-for-changes") {
|
|
280
|
+
throw new Error(`Change checks must run before dispatching Agent ${agent.name} to the worker`);
|
|
281
|
+
}
|
|
282
|
+
const execution = executeAgentScanPlan(
|
|
283
|
+
agent,
|
|
284
|
+
scanPlan,
|
|
285
|
+
{ sessions: previousSessions, meta: previousMeta },
|
|
286
|
+
{ ...data.scanOptions, onProgress: reportProgress }
|
|
287
|
+
);
|
|
288
|
+
let sessions = execution.sessions;
|
|
289
|
+
const changedIds = execution.changedSessionIds;
|
|
290
|
+
const sourceFailures = execution.sourceFailures;
|
|
291
|
+
const explicitRemovedSessionIds = execution.explicitRemovedSessionIds;
|
|
292
|
+
let finalizeSessionIds = execution.finalizeSessionIds === void 0 ? void 0 : new Set(execution.finalizeSessionIds);
|
|
263
293
|
let backfillOrder;
|
|
264
294
|
let backfillCursorIndex = -1;
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
const result = synchronizeSessionSources(
|
|
275
|
-
agent,
|
|
276
|
-
{ sessions: previousSessions, meta: previousMeta },
|
|
277
|
-
{
|
|
278
|
-
kind: "refresh",
|
|
279
|
-
scanOptions: { ...data.scanOptions, onProgress: reportProgress }
|
|
280
|
-
}
|
|
281
|
-
);
|
|
282
|
-
sessions = result.sessions;
|
|
283
|
-
changedIds = result.changedSessionIds;
|
|
284
|
-
finalizeSessionIds = new Set(result.finalizeSessionIds);
|
|
285
|
-
sourceSynchronizationDetails = {
|
|
286
|
-
sourceCount: result.sourceCount,
|
|
287
|
-
removedCount: result.removedSourceCount
|
|
288
|
-
};
|
|
289
|
-
sourceFailures = result.sourceFailures;
|
|
290
|
-
explicitRemovedSessionIds = result.explicitRemovedSessionIds;
|
|
291
|
-
} else if (operation.kind === "incremental-scan") {
|
|
292
|
-
changedIds = operation.changedIds;
|
|
293
|
-
sessions = inheritSmartTags(
|
|
294
|
-
await Promise.resolve(
|
|
295
|
-
agent.incrementalScan(previousSessions, operation.changedIds, void 0, {
|
|
296
|
-
...data.scanOptions,
|
|
297
|
-
onProgress: reportProgress
|
|
298
|
-
})
|
|
299
|
-
),
|
|
300
|
-
previousSessions
|
|
301
|
-
);
|
|
302
|
-
} else if (agent instanceof FileSystemSessionSource) {
|
|
303
|
-
const result = synchronizeSessionSources(
|
|
304
|
-
agent,
|
|
305
|
-
{ sessions: previousSessions, meta: previousMeta },
|
|
306
|
-
{
|
|
307
|
-
kind: "reload",
|
|
308
|
-
scanOptions: { ...data.scanOptions, onProgress: reportProgress }
|
|
309
|
-
}
|
|
310
|
-
);
|
|
311
|
-
sessions = result.sessions;
|
|
312
|
-
finalizeSessionIds = new Set(result.finalizeSessionIds);
|
|
313
|
-
sourceFailures = result.sourceFailures;
|
|
314
|
-
explicitRemovedSessionIds = result.explicitRemovedSessionIds;
|
|
315
|
-
} else {
|
|
316
|
-
sessions = inheritSmartTags(
|
|
317
|
-
await Promise.resolve(
|
|
318
|
-
agent.scan({
|
|
319
|
-
...data.scanOptions,
|
|
320
|
-
onProgress: reportProgress
|
|
321
|
-
})
|
|
322
|
-
),
|
|
323
|
-
previousSessions
|
|
324
|
-
);
|
|
325
|
-
}
|
|
295
|
+
const sourceSynchronizationDetails = execution.sourceSynchronization ? {
|
|
296
|
+
sourceCount: execution.sourceSynchronization.sourceCount,
|
|
297
|
+
removedCount: execution.sourceSynchronization.removedSourceCount,
|
|
298
|
+
enumerationMs: execution.sourceSynchronization.timing.enumerationMs,
|
|
299
|
+
diffMs: execution.sourceSynchronization.timing.diffMs,
|
|
300
|
+
parseMs: execution.sourceSynchronization.timing.parseMs,
|
|
301
|
+
changedCount: execution.sourceSynchronization.timing.changedSourceCount,
|
|
302
|
+
processedCount: execution.sourceSynchronization.timing.processedSourceCount
|
|
303
|
+
} : void 0;
|
|
326
304
|
sessions = attachMissingProjectIdentities(sessions);
|
|
327
|
-
const completeness =
|
|
305
|
+
const completeness = execution.completeness;
|
|
328
306
|
if (durableCheckpoints) {
|
|
329
307
|
const ordered = sortSessions(sessions);
|
|
330
308
|
parentPort?.postMessage({
|
|
@@ -334,7 +312,10 @@ async function run(data, progressEmitter) {
|
|
|
334
312
|
checkpoint: {
|
|
335
313
|
stage: "scanned",
|
|
336
314
|
sessions: ordered,
|
|
337
|
-
meta: buildAgentCacheMeta(
|
|
315
|
+
meta: buildAgentCacheMeta(
|
|
316
|
+
agent,
|
|
317
|
+
new Set(ordered.map((session) => session.reference.sessionId))
|
|
318
|
+
),
|
|
338
319
|
completeness
|
|
339
320
|
}
|
|
340
321
|
});
|
|
@@ -356,12 +337,17 @@ async function run(data, progressEmitter) {
|
|
|
356
337
|
changed_ids: changedIds?.length ?? 0,
|
|
357
338
|
source_count: sourceSynchronizationDetails?.sourceCount,
|
|
358
339
|
removed_count: sourceSynchronizationDetails?.removedCount,
|
|
340
|
+
source_enumeration_ms: roundMilliseconds(sourceSynchronizationDetails?.enumerationMs ?? 0),
|
|
341
|
+
source_diff_ms: roundMilliseconds(sourceSynchronizationDetails?.diffMs ?? 0),
|
|
342
|
+
source_parse_ms: roundMilliseconds(sourceSynchronizationDetails?.parseMs ?? 0),
|
|
343
|
+
changed_sources: sourceSynchronizationDetails?.changedCount,
|
|
344
|
+
processed_sources: sourceSynchronizationDetails?.processedCount,
|
|
359
345
|
failed_sources: sourceFailures.length,
|
|
360
346
|
duration_ms: Math.round(scanDuration)
|
|
361
347
|
});
|
|
362
348
|
const finalizeStartedAt = performance.now();
|
|
363
349
|
const finalizationTiming = createSessionFinalizationTiming();
|
|
364
|
-
const backfillPositionById = backfillOrder ? new Map(backfillOrder.map((session, index) => [session.
|
|
350
|
+
const backfillPositionById = backfillOrder ? new Map(backfillOrder.map((session, index) => [session.reference.sessionId, index])) : void 0;
|
|
365
351
|
sessions = finalizeSessions(
|
|
366
352
|
agent,
|
|
367
353
|
sessions,
|
|
@@ -371,14 +357,14 @@ async function run(data, progressEmitter) {
|
|
|
371
357
|
if (checkpoint.stage === "finalizing" && backfillOrder && backfillPositionById) {
|
|
372
358
|
let nextCursorIndex = backfillCursorIndex;
|
|
373
359
|
for (const { session } of checkpoint.changes) {
|
|
374
|
-
const index = backfillPositionById.get(session.
|
|
360
|
+
const index = backfillPositionById.get(session.reference.sessionId);
|
|
375
361
|
if (index != null && index > nextCursorIndex) nextCursorIndex = index;
|
|
376
362
|
}
|
|
377
363
|
if (nextCursorIndex > backfillCursorIndex) {
|
|
378
364
|
backfillCursorIndex = nextCursorIndex;
|
|
379
365
|
nextCheckpoint = {
|
|
380
366
|
...checkpoint,
|
|
381
|
-
backfillCursor: backfillOrder[nextCursorIndex]?.
|
|
367
|
+
backfillCursor: backfillOrder[nextCursorIndex]?.reference.sessionId
|
|
382
368
|
};
|
|
383
369
|
}
|
|
384
370
|
}
|
|
@@ -415,7 +401,7 @@ async function run(data, progressEmitter) {
|
|
|
415
401
|
appLogger.debug("scan.refresh_worker.finalized", {
|
|
416
402
|
agent: data.agentName,
|
|
417
403
|
operation: operation.kind,
|
|
418
|
-
backfill_cursor: backfillOrder?.[backfillCursorIndex]?.
|
|
404
|
+
backfill_cursor: backfillOrder?.[backfillCursorIndex]?.reference.sessionId,
|
|
419
405
|
sessions: sessions.length,
|
|
420
406
|
finalized_sessions: finalizationTiming.sessions,
|
|
421
407
|
batches: finalizationTiming.batches,
|
|
@@ -436,14 +422,19 @@ async function run(data, progressEmitter) {
|
|
|
436
422
|
duration_ms: roundMilliseconds(finalizationDuration),
|
|
437
423
|
total_duration_ms: Math.round(performance.now() - startedAt)
|
|
438
424
|
});
|
|
439
|
-
const nextMeta = buildAgentCacheMeta(
|
|
440
|
-
|
|
441
|
-
|
|
425
|
+
const nextMeta = buildAgentCacheMeta(
|
|
426
|
+
agent,
|
|
427
|
+
new Set(sessions.map((session) => session.reference.sessionId))
|
|
428
|
+
);
|
|
429
|
+
const delta = buildScanRefreshDelta({
|
|
442
430
|
previousSessions,
|
|
443
431
|
sessions,
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
432
|
+
previousMeta,
|
|
433
|
+
nextMeta,
|
|
434
|
+
changedIds,
|
|
435
|
+
completeness,
|
|
436
|
+
explicitRemovedSessionIds
|
|
437
|
+
});
|
|
447
438
|
baseline.staged = {
|
|
448
439
|
requestId: data.requestId,
|
|
449
440
|
generation: baseline.generation,
|
|
@@ -455,10 +446,7 @@ async function run(data, progressEmitter) {
|
|
|
455
446
|
type: "done",
|
|
456
447
|
requestId: data.requestId,
|
|
457
448
|
generation: baseline.generation,
|
|
458
|
-
|
|
459
|
-
removedSessionIds: diff.removedSessionIds,
|
|
460
|
-
meta: metaDiff.changes,
|
|
461
|
-
removedMetaIds: metaDiff.removedIds,
|
|
449
|
+
...delta,
|
|
462
450
|
sourceFailures,
|
|
463
451
|
completeness,
|
|
464
452
|
explicitRemovedSessionIds,
|
|
@@ -506,11 +494,13 @@ function commitBaseline(data) {
|
|
|
506
494
|
workerBaseline.staged = null;
|
|
507
495
|
}
|
|
508
496
|
function postRequestError(data, error, startedAt) {
|
|
497
|
+
const errorCode = error instanceof AgentUnavailableDuringScanError ? error.code : void 0;
|
|
509
498
|
parentPort?.postMessage({
|
|
510
499
|
type: "error",
|
|
511
500
|
requestId: data.requestId,
|
|
512
501
|
generation: data.generation,
|
|
513
502
|
error: error instanceof Error ? error.message : String(error),
|
|
503
|
+
...errorCode ? { errorCode } : {},
|
|
514
504
|
durationMs: performance.now() - startedAt
|
|
515
505
|
});
|
|
516
506
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/scan-refresh-worker.ts","../src/monotonic-value-sampler.ts","../src/scan-refresh-operation.ts"],"sourcesContent":["import \"./diagnostics-bridge.js\";\nimport { parentPort, workerData } from \"node:worker_threads\";\nimport { isDeepStrictEqual } from \"node:util\";\nimport {\n attachMissingProjectIdentities,\n buildAgentCacheMeta,\n computeSessionDiff,\n createRegisteredAgents,\n ensureSessionTagsSync,\n FileSystemSessionSource,\n sessionSignature,\n SMART_TAG_CLASSIFIER_REVISION,\n sortSessions,\n synchronizePricingGeneration,\n synchronizeSessionSources,\n type AgentScanProgress,\n type BaseAgent,\n type ScanOptions,\n type SessionCacheMeta,\n type SessionHead,\n type SessionHeadChange,\n type SessionSourceFailure,\n type SessionSnapshotCompleteness,\n type SessionTagTiming,\n} from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\nimport { MonotonicValueSampler } from \"./monotonic-value-sampler.js\";\nimport {\n isBackfillOperation,\n synchronizesSessionSources,\n usesDurableCheckpoints,\n type ScanRefreshOperation,\n} from \"./scan-refresh-operation.js\";\n\nexport type ScanRefreshWorkerMessage =\n | {\n type: \"progress\";\n requestId: number;\n generation: number;\n progress: AgentScanProgress;\n }\n | {\n type: \"checkpoint\";\n requestId: number;\n generation: number;\n checkpoint: ScanRefreshWorkerCheckpoint;\n }\n | {\n type: \"done\";\n requestId: number;\n generation: number;\n changes: SessionHeadChange[];\n removedSessionIds: string[];\n meta: Record<string, SessionCacheMeta>;\n removedMetaIds: string[];\n sourceFailures: SessionSourceFailure[];\n completeness: SessionSnapshotCompleteness;\n explicitRemovedSessionIds: string[];\n durationMs: number;\n }\n | {\n type: \"error\";\n requestId: number;\n generation: number;\n error: string;\n durationMs: number;\n };\n\nexport type ScanRefreshWorkerCheckpoint =\n | {\n stage: \"scanned\";\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n completeness: SessionSnapshotCompleteness;\n }\n | {\n stage: \"finalizing\";\n changes: SessionHeadChange[];\n meta: Record<string, SessionCacheMeta>;\n backfillCursor?: string;\n };\n\nexport interface ScanRefreshWorkerRunRequest {\n type: \"run\";\n requestId: number;\n agentName: string;\n generation: number;\n pricingGenerationId: number;\n previousSessions?: SessionHead[];\n operation: ScanRefreshOperation;\n scanOptions: Pick<ScanOptions, \"from\" | \"to\" | \"fast\">;\n meta?: Record<string, SessionCacheMeta>;\n}\n\nexport interface ScanRefreshWorkerCommitRequest {\n type: \"commit\";\n requestId: number;\n generation: number;\n}\n\nexport type ScanRefreshWorkerRequest = ScanRefreshWorkerRunRequest | ScanRefreshWorkerCommitRequest;\n\ninterface StagedWorkerBaseline {\n requestId: number;\n generation: number;\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n}\n\ninterface WorkerBaseline {\n agentName: string;\n agent: BaseAgent;\n generation: number;\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n staged: StagedWorkerBaseline | null;\n}\n\ninterface CacheMetaDiff {\n changes: Record<string, SessionCacheMeta>;\n removedIds: string[];\n}\n\nfunction computeCacheMetaDiff(\n previous: Record<string, SessionCacheMeta>,\n next: Record<string, SessionCacheMeta>,\n): CacheMetaDiff {\n const changes: Record<string, SessionCacheMeta> = {};\n const removedIds: string[] = [];\n for (const [id, meta] of Object.entries(next)) {\n if (!isDeepStrictEqual(previous[id], meta)) changes[id] = meta;\n }\n for (const id of Object.keys(previous)) {\n if (!Object.hasOwn(next, id)) removedIds.push(id);\n }\n return { changes, removedIds };\n}\n\nfunction hasStaleSmartTags(session: SessionHead): boolean {\n const sourceUpdatedAt = session.time_updated ?? session.time_created;\n return (\n !Array.isArray(session.smart_tags) ||\n session.smart_tags_source_updated_at !== sourceUpdatedAt ||\n session.smart_tags_classifier_revision !== SMART_TAG_CLASSIFIER_REVISION\n );\n}\n\ninterface BackfillSelection {\n orderedSessions: SessionHead[];\n finalizeSessionIds: ReadonlySet<string>;\n cursorIndex: number;\n}\n\nfunction selectBackfillSessions(\n sessions: SessionHead[],\n changedIds: string[],\n cursor: string | null | undefined,\n): BackfillSelection {\n const orderedSessions = sortSessions(sessions);\n const cursorIndex = cursor ? orderedSessions.findIndex((session) => session.id === cursor) : -1;\n const finalizeSessionIds = new Set<string>();\n const startIndex = cursorIndex >= 0 ? cursorIndex + 1 : 0;\n\n for (let index = startIndex; index < orderedSessions.length; index += 1) {\n finalizeSessionIds.add(orderedSessions[index]!.id);\n }\n\n for (const changedId of changedIds) finalizeSessionIds.add(changedId);\n\n // A hot session before the cursor remains stale until it settles. Keep it in\n // the next pass so it is not permanently skipped when it becomes idle.\n for (let index = 0; index <= cursorIndex; index += 1) {\n const session = orderedSessions[index]!;\n if (hasStaleSmartTags(session)) finalizeSessionIds.add(session.id);\n }\n\n return { orderedSessions, finalizeSessionIds, cursorIndex };\n}\n\n/**\n * scan() rebuilds heads from the source without smart tags, which would force\n * a full reclassification pass (one getSessionData() per session). Carry the\n * previous tags over and let the staleness check in ensureSessionTagsSync —\n * smart_tags_source_updated_at vs time_updated — decide what to recompute.\n */\nfunction inheritSmartTags(sessions: SessionHead[], previousSessions: SessionHead[]): SessionHead[] {\n const previousById = new Map(previousSessions.map((session) => [session.id, session]));\n return sessions.map((session) => {\n if (Array.isArray(session.smart_tags)) return session;\n const previous = previousById.get(session.id);\n if (!previous || !Array.isArray(previous.smart_tags)) return session;\n return {\n ...session,\n smart_tags: previous.smart_tags,\n smart_tags_source_updated_at: previous.smart_tags_source_updated_at,\n smart_tags_classifier_revision: previous.smart_tags_classifier_revision,\n };\n });\n}\n\n/**\n * A session still receiving writes will be stale again within seconds, so\n * recomputing its tags every refresh cycle is wasted work — wait for it to\n * settle before paying the getSessionData() parse cost.\n */\nconst TAG_SETTLE_MS = 60_000;\nconst TAG_CHECKPOINT_SIZE = 32;\nconst PROGRESS_INTERVAL_MS = 100;\n\ninterface SessionFinalizationTiming extends SessionTagTiming {\n batches: number;\n}\n\nfunction createSessionFinalizationTiming(): SessionFinalizationTiming {\n return {\n batches: 0,\n sessions: 0,\n cacheHits: 0,\n staleSessions: 0,\n failedSessions: 0,\n getSessionDataCalls: 0,\n getSessionDataMs: 0,\n classifySessionTagsCalls: 0,\n classifySessionTagsMs: 0,\n };\n}\n\nfunction addSessionTagTiming(target: SessionFinalizationTiming, source: SessionTagTiming): void {\n target.sessions += source.sessions;\n target.cacheHits += source.cacheHits;\n target.staleSessions += source.staleSessions;\n target.failedSessions += source.failedSessions;\n target.getSessionDataCalls += source.getSessionDataCalls;\n target.getSessionDataMs += source.getSessionDataMs;\n target.classifySessionTagsCalls += source.classifySessionTagsCalls;\n target.classifySessionTagsMs += source.classifySessionTagsMs;\n}\n\nfunction roundMilliseconds(value: number): number {\n return Math.round(value * 100) / 100;\n}\n\nfunction isSettled(session: SessionHead, now: number): boolean {\n return now - (session.time_updated ?? session.time_created) >= TAG_SETTLE_MS;\n}\n\n/**\n * Runs identity resolution (spawns git) and stale smart-tag reclassification\n * on the worker thread, off the server's main event loop.\n */\nexport function finalizeSessions(\n agent: BaseAgent,\n sessions: SessionHead[],\n onProgress?: (progress: AgentScanProgress) => void,\n onCheckpoint?: (checkpoint: ScanRefreshWorkerCheckpoint) => void,\n finalizeSessionIds?: ReadonlySet<string>,\n onTiming?: (timing: SessionTagTiming) => void,\n): SessionHead[] {\n const ordered = sortSessions(attachMissingProjectIdentities(sessions));\n\n const now = Date.now();\n const settled = ordered.filter(\n (session) =>\n (!finalizeSessionIds || finalizeSessionIds.has(session.id)) && isSettled(session, now),\n );\n if (settled.length === 0) return ordered;\n\n let lastReportedAt = -Infinity;\n const reportProgress = (processed: number, total: number): void => {\n const now = performance.now();\n if (processed !== 0 && processed !== total && now - lastReportedAt < 100) return;\n lastReportedAt = now;\n onProgress?.({\n phase: \"finalizing\",\n total,\n processed,\n sessions: ordered.length,\n });\n };\n reportProgress(0, settled.length);\n\n const sortIndexById = new Map(ordered.map((session, index) => [session.id, index]));\n const taggedById = new Map<string, SessionHead>();\n for (let start = 0; start < settled.length; start += TAG_CHECKPOINT_SIZE) {\n const batch = settled.slice(start, start + TAG_CHECKPOINT_SIZE);\n const taggedResult = ensureSessionTagsSync(agent, batch, (processed) => {\n reportProgress(start + processed, settled.length);\n });\n if (taggedResult.timing) onTiming?.(taggedResult.timing);\n const taggedBatch = taggedResult.sessions;\n for (const session of taggedBatch) taggedById.set(session.id, session);\n\n onCheckpoint?.({\n stage: \"finalizing\",\n changes: taggedBatch.map((session) => ({\n session,\n sortIndex: sortIndexById.get(session.id) ?? 0,\n })),\n meta: buildAgentCacheMeta(agent, new Set(taggedBatch.map((session) => session.id))),\n });\n }\n return ordered.map((session) => taggedById.get(session.id) ?? session);\n}\n\nlet workerBaseline: WorkerBaseline | null = null;\n\nfunction baselineFor(data: ScanRefreshWorkerRunRequest): WorkerBaseline {\n const generation = data.generation ?? 0;\n const hasSessions = Array.isArray(data.previousSessions);\n const hasMeta = data.meta != null;\n if (hasSessions !== hasMeta)\n throw new Error(\"Worker baseline requires sessions and meta together\");\n\n if (hasSessions && hasMeta) {\n if (workerBaseline) throw new Error(\"Scan refresh worker baseline is already initialized\");\n const agent = createRegisteredAgents().find((item) => item.name === data.agentName);\n if (!agent) throw new Error(`Unknown agent: ${data.agentName}`);\n workerBaseline = {\n agentName: data.agentName,\n agent,\n generation,\n sessions: data.previousSessions!,\n meta: data.meta!,\n staged: null,\n };\n }\n\n if (!workerBaseline) throw new Error(\"Scan refresh worker baseline is not initialized\");\n if (workerBaseline.agentName !== data.agentName) {\n throw new Error(`Worker Agent mismatch: expected ${workerBaseline.agentName}`);\n }\n if (workerBaseline.generation !== generation) {\n throw new Error(\n `Worker generation mismatch: expected ${workerBaseline.generation}, received ${generation}`,\n );\n }\n if (workerBaseline.staged) {\n throw new Error(`Worker result ${workerBaseline.staged.requestId} is awaiting commit`);\n }\n\n workerBaseline.agent.setSessionMetaMap(new Map(Object.entries(workerBaseline.meta)));\n return workerBaseline;\n}\n\nasync function run(\n data: ScanRefreshWorkerRunRequest,\n progressEmitter: MonotonicValueSampler<AgentScanProgress>,\n): Promise<void> {\n const startedAt = performance.now();\n const baseline = baselineFor(data);\n const { agent } = baseline;\n const previousSessions = baseline.sessions;\n const previousMeta = baseline.meta;\n const operation = data.operation;\n const sourceSynchronization = synchronizesSessionSources(operation);\n const backfill = isBackfillOperation(operation);\n const durableCheckpoints = usesDurableCheckpoints(operation);\n const backfillCursor = backfill ? operation.cursor : undefined;\n\n appLogger.debug(\"scan.refresh_worker.started\", {\n agent: data.agentName,\n operation: operation.kind,\n backfill_cursor: backfillCursor ?? undefined,\n changed_ids: operation.kind === \"incremental-scan\" ? operation.changedIds.length : 0,\n previous_sessions: previousSessions.length,\n });\n\n const reportProgress = (progress: AgentScanProgress): void => {\n progressEmitter.push(progress, progress.phase ?? \"scanning\");\n };\n\n const isAvailable = agent.isAvailable();\n let sessions: SessionHead[];\n let changedIds: string[] | undefined;\n let sourceFailures: SessionSourceFailure[] = [];\n let explicitRemovedSessionIds: string[] = [];\n let finalizeSessionIds: ReadonlySet<string> | undefined;\n let backfillOrder: SessionHead[] | undefined;\n let backfillCursorIndex = -1;\n let sourceSynchronizationDetails:\n | {\n sourceCount: number;\n removedCount: number;\n }\n | undefined;\n\n if (!isAvailable) {\n sessions = [];\n } else if (operation.kind === \"recompute-derived\") {\n sessions = previousSessions;\n } else if (sourceSynchronization) {\n if (!(agent instanceof FileSystemSessionSource)) {\n throw new Error(`Agent ${agent.name} does not support Session Source synchronization`);\n }\n const result = synchronizeSessionSources(\n agent,\n { sessions: previousSessions, meta: previousMeta },\n {\n kind: \"refresh\",\n scanOptions: { ...data.scanOptions, onProgress: reportProgress },\n },\n );\n sessions = result.sessions;\n changedIds = result.changedSessionIds;\n finalizeSessionIds = new Set(result.finalizeSessionIds);\n sourceSynchronizationDetails = {\n sourceCount: result.sourceCount,\n removedCount: result.removedSourceCount,\n };\n sourceFailures = result.sourceFailures;\n explicitRemovedSessionIds = result.explicitRemovedSessionIds;\n } else if (operation.kind === \"incremental-scan\") {\n changedIds = operation.changedIds;\n sessions = inheritSmartTags(\n await Promise.resolve(\n agent.incrementalScan(previousSessions, operation.changedIds, undefined, {\n ...data.scanOptions,\n onProgress: reportProgress,\n }),\n ),\n previousSessions,\n );\n } else if (agent instanceof FileSystemSessionSource) {\n const result = synchronizeSessionSources(\n agent,\n { sessions: previousSessions, meta: previousMeta },\n {\n kind: \"reload\",\n scanOptions: { ...data.scanOptions, onProgress: reportProgress },\n },\n );\n sessions = result.sessions;\n finalizeSessionIds = new Set(result.finalizeSessionIds);\n sourceFailures = result.sourceFailures;\n explicitRemovedSessionIds = result.explicitRemovedSessionIds;\n } else {\n sessions = inheritSmartTags(\n await Promise.resolve(\n agent.scan({\n ...data.scanOptions,\n onProgress: reportProgress,\n }),\n ),\n previousSessions,\n );\n }\n\n sessions = attachMissingProjectIdentities(sessions);\n const completeness: SessionSnapshotCompleteness =\n data.scanOptions.from == null && data.scanOptions.to == null && sourceFailures.length === 0\n ? \"complete\"\n : \"partial\";\n if (durableCheckpoints) {\n const ordered = sortSessions(sessions);\n parentPort?.postMessage({\n type: \"checkpoint\",\n requestId: data.requestId,\n generation: baseline.generation,\n checkpoint: {\n stage: \"scanned\",\n sessions: ordered,\n meta: buildAgentCacheMeta(agent, new Set(ordered.map((session) => session.id))),\n completeness,\n },\n } satisfies ScanRefreshWorkerMessage);\n sessions = ordered;\n }\n\n if (backfill) {\n const selection = selectBackfillSessions(sessions, changedIds ?? [], backfillCursor);\n sessions = selection.orderedSessions;\n finalizeSessionIds = selection.finalizeSessionIds;\n backfillOrder = selection.orderedSessions;\n backfillCursorIndex = selection.cursorIndex;\n }\n\n const scanDuration = performance.now() - startedAt;\n appLogger.debug(\"scan.refresh_worker.scanned\", {\n agent: data.agentName,\n operation: operation.kind,\n backfill_cursor: backfillCursor ?? undefined,\n sessions: sessions.length,\n changed_ids: changedIds?.length ?? 0,\n source_count: sourceSynchronizationDetails?.sourceCount,\n removed_count: sourceSynchronizationDetails?.removedCount,\n failed_sources: sourceFailures.length,\n duration_ms: Math.round(scanDuration),\n });\n\n const finalizeStartedAt = performance.now();\n const finalizationTiming = createSessionFinalizationTiming();\n const backfillPositionById = backfillOrder\n ? new Map(backfillOrder.map((session, index) => [session.id, index]))\n : undefined;\n sessions = finalizeSessions(\n agent,\n sessions,\n reportProgress,\n durableCheckpoints\n ? (checkpoint) => {\n let nextCheckpoint = checkpoint;\n if (checkpoint.stage === \"finalizing\" && backfillOrder && backfillPositionById) {\n let nextCursorIndex = backfillCursorIndex;\n for (const { session } of checkpoint.changes) {\n const index = backfillPositionById.get(session.id);\n if (index != null && index > nextCursorIndex) nextCursorIndex = index;\n }\n if (nextCursorIndex > backfillCursorIndex) {\n backfillCursorIndex = nextCursorIndex;\n nextCheckpoint = {\n ...checkpoint,\n backfillCursor: backfillOrder[nextCursorIndex]?.id,\n };\n }\n }\n parentPort?.postMessage({\n type: \"checkpoint\",\n requestId: data.requestId,\n generation: baseline.generation,\n checkpoint: nextCheckpoint,\n } satisfies ScanRefreshWorkerMessage);\n }\n : undefined,\n finalizeSessionIds,\n (batchTiming) => {\n finalizationTiming.batches += 1;\n addSessionTagTiming(finalizationTiming, batchTiming);\n appLogger.debug(\"scan.refresh_worker.finalization_batch\", {\n agent: data.agentName,\n batch: finalizationTiming.batches,\n sessions: batchTiming.sessions,\n cache_hits: batchTiming.cacheHits,\n stale_sessions: batchTiming.staleSessions,\n failed_sessions: batchTiming.failedSessions,\n get_session_data_calls: batchTiming.getSessionDataCalls,\n get_session_data_ms: roundMilliseconds(batchTiming.getSessionDataMs),\n classify_session_tags_calls: batchTiming.classifySessionTagsCalls,\n classify_session_tags_ms: roundMilliseconds(batchTiming.classifySessionTagsMs),\n });\n },\n );\n const finalizationDuration = performance.now() - finalizeStartedAt;\n const otherFinalizationMs = Math.max(\n 0,\n finalizationDuration -\n finalizationTiming.getSessionDataMs -\n finalizationTiming.classifySessionTagsMs,\n );\n appLogger.debug(\"scan.refresh_worker.finalized\", {\n agent: data.agentName,\n operation: operation.kind,\n backfill_cursor: backfillOrder?.[backfillCursorIndex]?.id,\n sessions: sessions.length,\n finalized_sessions: finalizationTiming.sessions,\n batches: finalizationTiming.batches,\n cache_hits: finalizationTiming.cacheHits,\n stale_sessions: finalizationTiming.staleSessions,\n failed_sessions: finalizationTiming.failedSessions,\n get_session_data_calls: finalizationTiming.getSessionDataCalls,\n get_session_data_ms: roundMilliseconds(finalizationTiming.getSessionDataMs),\n get_session_data_avg_ms: roundMilliseconds(\n finalizationTiming.getSessionDataCalls > 0\n ? finalizationTiming.getSessionDataMs / finalizationTiming.getSessionDataCalls\n : 0,\n ),\n classify_session_tags_calls: finalizationTiming.classifySessionTagsCalls,\n classify_session_tags_ms: roundMilliseconds(finalizationTiming.classifySessionTagsMs),\n classify_session_tags_avg_ms: roundMilliseconds(\n finalizationTiming.classifySessionTagsCalls > 0\n ? finalizationTiming.classifySessionTagsMs / finalizationTiming.classifySessionTagsCalls\n : 0,\n ),\n other_finalization_ms: roundMilliseconds(otherFinalizationMs),\n duration_ms: roundMilliseconds(finalizationDuration),\n total_duration_ms: Math.round(performance.now() - startedAt),\n });\n const nextMeta = buildAgentCacheMeta(agent, new Set(sessions.map((session) => session.id)));\n const metaDiff = computeCacheMetaDiff(previousMeta, nextMeta);\n const diff = computeSessionDiff(\n previousSessions,\n sessions,\n [...(changedIds ?? []), ...Object.keys(metaDiff.changes), ...metaDiff.removedIds],\n sessionSignature,\n );\n\n baseline.staged = {\n requestId: data.requestId,\n generation: baseline.generation,\n sessions,\n meta: nextMeta,\n };\n progressEmitter.flush();\n parentPort?.postMessage({\n type: \"done\",\n requestId: data.requestId,\n generation: baseline.generation,\n changes: diff.changes,\n removedSessionIds: diff.removedSessionIds,\n meta: metaDiff.changes,\n removedMetaIds: metaDiff.removedIds,\n sourceFailures,\n completeness,\n explicitRemovedSessionIds,\n durationMs: performance.now() - startedAt,\n } satisfies ScanRefreshWorkerMessage);\n}\n\nasync function handleRequest(data: ScanRefreshWorkerRunRequest): Promise<void> {\n const startedAt = performance.now();\n const progressEmitter = new MonotonicValueSampler<AgentScanProgress>(\n PROGRESS_INTERVAL_MS,\n (progress) => {\n parentPort?.postMessage({\n type: \"progress\",\n requestId: data.requestId,\n generation: data.generation ?? 0,\n progress,\n } satisfies ScanRefreshWorkerMessage);\n },\n );\n try {\n synchronizePricingGeneration(data.pricingGenerationId);\n await run(data, progressEmitter);\n } catch (error) {\n progressEmitter.flush();\n postRequestError(data, error, startedAt);\n } finally {\n progressEmitter.cancel();\n }\n}\n\nlet requestTail = Promise.resolve();\n\nfunction commitBaseline(data: ScanRefreshWorkerCommitRequest): void {\n if (!workerBaseline) throw new Error(\"Cannot commit an uninitialized worker baseline\");\n const staged = workerBaseline.staged;\n if (!staged || staged.requestId !== data.requestId) {\n throw new Error(`Worker result ${data.requestId} is not awaiting commit`);\n }\n if (workerBaseline.generation !== data.generation || staged.generation !== data.generation) {\n throw new Error(\n `Worker commit generation mismatch: expected ${workerBaseline.generation}, received ${data.generation}`,\n );\n }\n workerBaseline.sessions = staged.sessions;\n workerBaseline.meta = staged.meta;\n workerBaseline.generation += 1;\n workerBaseline.staged = null;\n}\n\nfunction postRequestError(data: ScanRefreshWorkerRequest, error: unknown, startedAt: number): void {\n parentPort?.postMessage({\n type: \"error\",\n requestId: data.requestId,\n generation: data.generation,\n error: error instanceof Error ? error.message : String(error),\n durationMs: performance.now() - startedAt,\n } satisfies ScanRefreshWorkerMessage);\n}\n\nfunction handleCommit(data: ScanRefreshWorkerCommitRequest): void {\n const startedAt = performance.now();\n try {\n commitBaseline(data);\n } catch (error) {\n postRequestError(data, error, startedAt);\n }\n}\n\nfunction enqueueRequest(data: ScanRefreshWorkerRequest): void {\n requestTail = requestTail\n .then(() => (data.type === \"commit\" ? handleCommit(data) : handleRequest(data)))\n .catch((error) => {\n appLogger.error(\"scan.refresh_worker.request_error\", {\n request_id: data.requestId,\n request_type: data.type,\n error,\n });\n });\n}\n\nconst initialRequest = workerData as Partial<ScanRefreshWorkerRequest> | undefined;\nif (\n initialRequest?.type === \"run\" &&\n typeof initialRequest.requestId === \"number\" &&\n typeof initialRequest.agentName === \"string\" &&\n typeof initialRequest.pricingGenerationId === \"number\" &&\n initialRequest.operation != null &&\n Array.isArray(initialRequest.previousSessions) &&\n initialRequest.meta != null\n) {\n enqueueRequest(initialRequest as ScanRefreshWorkerRunRequest);\n}\n\nparentPort?.on(\"message\", (message: ScanRefreshWorkerRequest) => {\n enqueueRequest(message);\n});\n","export class MonotonicValueSampler<Value> {\n private phase: string | null = null;\n private lastEmittedAt = -Infinity;\n private pending: Value | undefined;\n private hasPending = false;\n\n constructor(\n private readonly intervalMs: number,\n private readonly emit: (value: Value) => void,\n private readonly now: () => number = () => performance.now(),\n ) {}\n\n push(value: Value, phase: string): void {\n if (this.phase !== phase) {\n this.flush();\n this.phase = phase;\n this.emitNow(value);\n return;\n }\n\n if (this.now() - this.lastEmittedAt >= this.intervalMs) {\n this.pending = undefined;\n this.hasPending = false;\n this.emitNow(value);\n return;\n }\n\n this.pending = value;\n this.hasPending = true;\n }\n\n flush(): void {\n if (!this.hasPending) return;\n const pending = this.pending as Value;\n this.pending = undefined;\n this.hasPending = false;\n this.emitNow(pending);\n }\n\n cancel(): void {\n this.phase = null;\n this.lastEmittedAt = -Infinity;\n this.pending = undefined;\n this.hasPending = false;\n }\n\n private emitNow(value: Value): void {\n this.lastEmittedAt = this.now();\n this.emit(value);\n }\n}\n","type DurableCheckpoint = { checkpoint?: \"durable\" };\n\nexport type ScanRefreshOperation =\n | ({ kind: \"full-scan\" } & DurableCheckpoint)\n | { kind: \"incremental-scan\"; changedIds: string[] }\n | ({ kind: \"source-refresh\" } & DurableCheckpoint)\n | { kind: \"recompute-derived\" }\n | ({ kind: \"full-backfill\"; cursor?: string | null } & DurableCheckpoint)\n | ({ kind: \"source-backfill\"; cursor?: string | null } & DurableCheckpoint);\n\nexport type BackfillScanRefreshOperation = Extract<\n ScanRefreshOperation,\n { kind: \"full-backfill\" | \"source-backfill\" }\n>;\n\nexport function synchronizesSessionSources(operation: ScanRefreshOperation): boolean {\n return operation.kind === \"source-refresh\" || operation.kind === \"source-backfill\";\n}\n\nexport function isBackfillOperation(\n operation: ScanRefreshOperation,\n): operation is BackfillScanRefreshOperation {\n return operation.kind === \"full-backfill\" || operation.kind === \"source-backfill\";\n}\n\nexport function usesDurableCheckpoints(operation: ScanRefreshOperation): boolean {\n return \"checkpoint\" in operation && operation.checkpoint === \"durable\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AACA,SAAS,YAAY,kBAAkB;AACvC,SAAS,yBAAyB;;;ACF3B,IAAM,wBAAN,MAAmC;AAAA,EAMxC,YACmB,YACA,MACA,MAAoB,MAAM,YAAY,IAAI,GAC3D;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAHgB;AAAA,EACA;AAAA,EACA;AAAA,EARX,QAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB;AAAA,EACA,aAAa;AAAA,EAQrB,KAAK,OAAc,OAAqB;AACtC,QAAI,KAAK,UAAU,OAAO;AACxB,WAAK,MAAM;AACX,WAAK,QAAQ;AACb,WAAK,QAAQ,KAAK;AAClB;AAAA,IACF;AAEA,QAAI,KAAK,IAAI,IAAI,KAAK,iBAAiB,KAAK,YAAY;AACtD,WAAK,UAAU;AACf,WAAK,aAAa;AAClB,WAAK,QAAQ,KAAK;AAClB;AAAA,IACF;AAEA,SAAK,UAAU;AACf,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,QAAc;AACZ,QAAI,CAAC,KAAK,WAAY;AACtB,UAAM,UAAU,KAAK;AACrB,SAAK,UAAU;AACf,SAAK,aAAa;AAClB,SAAK,QAAQ,OAAO;AAAA,EACtB;AAAA,EAEA,SAAe;AACb,SAAK,QAAQ;AACb,SAAK,gBAAgB;AACrB,SAAK,UAAU;AACf,SAAK,aAAa;AAAA,EACpB;AAAA,EAEQ,QAAQ,OAAoB;AAClC,SAAK,gBAAgB,KAAK,IAAI;AAC9B,SAAK,KAAK,KAAK;AAAA,EACjB;AACF;;;ACnCO,SAAS,2BAA2B,WAA0C;AACnF,SAAO,UAAU,SAAS,oBAAoB,UAAU,SAAS;AACnE;AAEO,SAAS,oBACd,WAC2C;AAC3C,SAAO,UAAU,SAAS,mBAAmB,UAAU,SAAS;AAClE;AAEO,SAAS,uBAAuB,WAA0C;AAC/E,SAAO,gBAAgB,aAAa,UAAU,eAAe;AAC/D;;;AFgGA,SAAS,qBACP,UACA,MACe;AACf,QAAM,UAA4C,CAAC;AACnD,QAAM,aAAuB,CAAC;AAC9B,aAAW,CAAC,IAAI,IAAI,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC7C,QAAI,CAAC,kBAAkB,SAAS,EAAE,GAAG,IAAI,EAAG,SAAQ,EAAE,IAAI;AAAA,EAC5D;AACA,aAAW,MAAM,OAAO,KAAK,QAAQ,GAAG;AACtC,QAAI,CAAC,OAAO,OAAO,MAAM,EAAE,EAAG,YAAW,KAAK,EAAE;AAAA,EAClD;AACA,SAAO,EAAE,SAAS,WAAW;AAC/B;AAEA,SAAS,kBAAkB,SAA+B;AACxD,QAAM,kBAAkB,QAAQ,gBAAgB,QAAQ;AACxD,SACE,CAAC,MAAM,QAAQ,QAAQ,UAAU,KACjC,QAAQ,iCAAiC,mBACzC,QAAQ,mCAAmC;AAE/C;AAQA,SAAS,uBACP,UACA,YACA,QACmB;AACnB,QAAM,kBAAkB,aAAa,QAAQ;AAC7C,QAAM,cAAc,SAAS,gBAAgB,UAAU,CAAC,YAAY,QAAQ,OAAO,MAAM,IAAI;AAC7F,QAAM,qBAAqB,oBAAI,IAAY;AAC3C,QAAM,aAAa,eAAe,IAAI,cAAc,IAAI;AAExD,WAAS,QAAQ,YAAY,QAAQ,gBAAgB,QAAQ,SAAS,GAAG;AACvE,uBAAmB,IAAI,gBAAgB,KAAK,EAAG,EAAE;AAAA,EACnD;AAEA,aAAW,aAAa,WAAY,oBAAmB,IAAI,SAAS;AAIpE,WAAS,QAAQ,GAAG,SAAS,aAAa,SAAS,GAAG;AACpD,UAAM,UAAU,gBAAgB,KAAK;AACrC,QAAI,kBAAkB,OAAO,EAAG,oBAAmB,IAAI,QAAQ,EAAE;AAAA,EACnE;AAEA,SAAO,EAAE,iBAAiB,oBAAoB,YAAY;AAC5D;AAQA,SAAS,iBAAiB,UAAyB,kBAAgD;AACjG,QAAM,eAAe,IAAI,IAAI,iBAAiB,IAAI,CAAC,YAAY,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC;AACrF,SAAO,SAAS,IAAI,CAAC,YAAY;AAC/B,QAAI,MAAM,QAAQ,QAAQ,UAAU,EAAG,QAAO;AAC9C,UAAM,WAAW,aAAa,IAAI,QAAQ,EAAE;AAC5C,QAAI,CAAC,YAAY,CAAC,MAAM,QAAQ,SAAS,UAAU,EAAG,QAAO;AAC7D,WAAO;AAAA,MACL,GAAG;AAAA,MACH,YAAY,SAAS;AAAA,MACrB,8BAA8B,SAAS;AAAA,MACvC,gCAAgC,SAAS;AAAA,IAC3C;AAAA,EACF,CAAC;AACH;AAOA,IAAM,gBAAgB;AACtB,IAAM,sBAAsB;AAC5B,IAAM,uBAAuB;AAM7B,SAAS,kCAA6D;AACpE,SAAO;AAAA,IACL,SAAS;AAAA,IACT,UAAU;AAAA,IACV,WAAW;AAAA,IACX,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,qBAAqB;AAAA,IACrB,kBAAkB;AAAA,IAClB,0BAA0B;AAAA,IAC1B,uBAAuB;AAAA,EACzB;AACF;AAEA,SAAS,oBAAoB,QAAmC,QAAgC;AAC9F,SAAO,YAAY,OAAO;AAC1B,SAAO,aAAa,OAAO;AAC3B,SAAO,iBAAiB,OAAO;AAC/B,SAAO,kBAAkB,OAAO;AAChC,SAAO,uBAAuB,OAAO;AACrC,SAAO,oBAAoB,OAAO;AAClC,SAAO,4BAA4B,OAAO;AAC1C,SAAO,yBAAyB,OAAO;AACzC;AAEA,SAAS,kBAAkB,OAAuB;AAChD,SAAO,KAAK,MAAM,QAAQ,GAAG,IAAI;AACnC;AAEA,SAAS,UAAU,SAAsB,KAAsB;AAC7D,SAAO,OAAO,QAAQ,gBAAgB,QAAQ,iBAAiB;AACjE;AAMO,SAAS,iBACd,OACA,UACA,YACA,cACA,oBACA,UACe;AACf,QAAM,UAAU,aAAa,+BAA+B,QAAQ,CAAC;AAErE,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,UAAU,QAAQ;AAAA,IACtB,CAAC,aACE,CAAC,sBAAsB,mBAAmB,IAAI,QAAQ,EAAE,MAAM,UAAU,SAAS,GAAG;AAAA,EACzF;AACA,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,MAAI,iBAAiB;AACrB,QAAM,iBAAiB,CAAC,WAAmB,UAAwB;AACjE,UAAMA,OAAM,YAAY,IAAI;AAC5B,QAAI,cAAc,KAAK,cAAc,SAASA,OAAM,iBAAiB,IAAK;AAC1E,qBAAiBA;AACjB,iBAAa;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,UAAU,QAAQ;AAAA,IACpB,CAAC;AAAA,EACH;AACA,iBAAe,GAAG,QAAQ,MAAM;AAEhC,QAAM,gBAAgB,IAAI,IAAI,QAAQ,IAAI,CAAC,SAAS,UAAU,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC;AAClF,QAAM,aAAa,oBAAI,IAAyB;AAChD,WAAS,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS,qBAAqB;AACxE,UAAM,QAAQ,QAAQ,MAAM,OAAO,QAAQ,mBAAmB;AAC9D,UAAM,eAAe,sBAAsB,OAAO,OAAO,CAAC,cAAc;AACtE,qBAAe,QAAQ,WAAW,QAAQ,MAAM;AAAA,IAClD,CAAC;AACD,QAAI,aAAa,OAAQ,YAAW,aAAa,MAAM;AACvD,UAAM,cAAc,aAAa;AACjC,eAAW,WAAW,YAAa,YAAW,IAAI,QAAQ,IAAI,OAAO;AAErE,mBAAe;AAAA,MACb,OAAO;AAAA,MACP,SAAS,YAAY,IAAI,CAAC,aAAa;AAAA,QACrC;AAAA,QACA,WAAW,cAAc,IAAI,QAAQ,EAAE,KAAK;AAAA,MAC9C,EAAE;AAAA,MACF,MAAM,oBAAoB,OAAO,IAAI,IAAI,YAAY,IAAI,CAAC,YAAY,QAAQ,EAAE,CAAC,CAAC;AAAA,IACpF,CAAC;AAAA,EACH;AACA,SAAO,QAAQ,IAAI,CAAC,YAAY,WAAW,IAAI,QAAQ,EAAE,KAAK,OAAO;AACvE;AAEA,IAAI,iBAAwC;AAE5C,SAAS,YAAY,MAAmD;AACtE,QAAM,aAAa,KAAK,cAAc;AACtC,QAAM,cAAc,MAAM,QAAQ,KAAK,gBAAgB;AACvD,QAAM,UAAU,KAAK,QAAQ;AAC7B,MAAI,gBAAgB;AAClB,UAAM,IAAI,MAAM,qDAAqD;AAEvE,MAAI,eAAe,SAAS;AAC1B,QAAI,eAAgB,OAAM,IAAI,MAAM,qDAAqD;AACzF,UAAM,QAAQ,uBAAuB,EAAE,KAAK,CAAC,SAAS,KAAK,SAAS,KAAK,SAAS;AAClF,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,kBAAkB,KAAK,SAAS,EAAE;AAC9D,qBAAiB;AAAA,MACf,WAAW,KAAK;AAAA,MAChB;AAAA,MACA;AAAA,MACA,UAAU,KAAK;AAAA,MACf,MAAM,KAAK;AAAA,MACX,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,CAAC,eAAgB,OAAM,IAAI,MAAM,iDAAiD;AACtF,MAAI,eAAe,cAAc,KAAK,WAAW;AAC/C,UAAM,IAAI,MAAM,mCAAmC,eAAe,SAAS,EAAE;AAAA,EAC/E;AACA,MAAI,eAAe,eAAe,YAAY;AAC5C,UAAM,IAAI;AAAA,MACR,wCAAwC,eAAe,UAAU,cAAc,UAAU;AAAA,IAC3F;AAAA,EACF;AACA,MAAI,eAAe,QAAQ;AACzB,UAAM,IAAI,MAAM,iBAAiB,eAAe,OAAO,SAAS,qBAAqB;AAAA,EACvF;AAEA,iBAAe,MAAM,kBAAkB,IAAI,IAAI,OAAO,QAAQ,eAAe,IAAI,CAAC,CAAC;AACnF,SAAO;AACT;AAEA,eAAe,IACb,MACA,iBACe;AACf,QAAM,YAAY,YAAY,IAAI;AAClC,QAAM,WAAW,YAAY,IAAI;AACjC,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,mBAAmB,SAAS;AAClC,QAAM,eAAe,SAAS;AAC9B,QAAM,YAAY,KAAK;AACvB,QAAM,wBAAwB,2BAA2B,SAAS;AAClE,QAAM,WAAW,oBAAoB,SAAS;AAC9C,QAAM,qBAAqB,uBAAuB,SAAS;AAC3D,QAAM,iBAAiB,WAAW,UAAU,SAAS;AAErD,YAAU,MAAM,+BAA+B;AAAA,IAC7C,OAAO,KAAK;AAAA,IACZ,WAAW,UAAU;AAAA,IACrB,iBAAiB,kBAAkB;AAAA,IACnC,aAAa,UAAU,SAAS,qBAAqB,UAAU,WAAW,SAAS;AAAA,IACnF,mBAAmB,iBAAiB;AAAA,EACtC,CAAC;AAED,QAAM,iBAAiB,CAAC,aAAsC;AAC5D,oBAAgB,KAAK,UAAU,SAAS,SAAS,UAAU;AAAA,EAC7D;AAEA,QAAM,cAAc,MAAM,YAAY;AACtC,MAAI;AACJ,MAAI;AACJ,MAAI,iBAAyC,CAAC;AAC9C,MAAI,4BAAsC,CAAC;AAC3C,MAAI;AACJ,MAAI;AACJ,MAAI,sBAAsB;AAC1B,MAAI;AAOJ,MAAI,CAAC,aAAa;AAChB,eAAW,CAAC;AAAA,EACd,WAAW,UAAU,SAAS,qBAAqB;AACjD,eAAW;AAAA,EACb,WAAW,uBAAuB;AAChC,QAAI,EAAE,iBAAiB,0BAA0B;AAC/C,YAAM,IAAI,MAAM,SAAS,MAAM,IAAI,kDAAkD;AAAA,IACvF;AACA,UAAM,SAAS;AAAA,MACb;AAAA,MACA,EAAE,UAAU,kBAAkB,MAAM,aAAa;AAAA,MACjD;AAAA,QACE,MAAM;AAAA,QACN,aAAa,EAAE,GAAG,KAAK,aAAa,YAAY,eAAe;AAAA,MACjE;AAAA,IACF;AACA,eAAW,OAAO;AAClB,iBAAa,OAAO;AACpB,yBAAqB,IAAI,IAAI,OAAO,kBAAkB;AACtD,mCAA+B;AAAA,MAC7B,aAAa,OAAO;AAAA,MACpB,cAAc,OAAO;AAAA,IACvB;AACA,qBAAiB,OAAO;AACxB,gCAA4B,OAAO;AAAA,EACrC,WAAW,UAAU,SAAS,oBAAoB;AAChD,iBAAa,UAAU;AACvB,eAAW;AAAA,MACT,MAAM,QAAQ;AAAA,QACZ,MAAM,gBAAgB,kBAAkB,UAAU,YAAY,QAAW;AAAA,UACvE,GAAG,KAAK;AAAA,UACR,YAAY;AAAA,QACd,CAAC;AAAA,MACH;AAAA,MACA;AAAA,IACF;AAAA,EACF,WAAW,iBAAiB,yBAAyB;AACnD,UAAM,SAAS;AAAA,MACb;AAAA,MACA,EAAE,UAAU,kBAAkB,MAAM,aAAa;AAAA,MACjD;AAAA,QACE,MAAM;AAAA,QACN,aAAa,EAAE,GAAG,KAAK,aAAa,YAAY,eAAe;AAAA,MACjE;AAAA,IACF;AACA,eAAW,OAAO;AAClB,yBAAqB,IAAI,IAAI,OAAO,kBAAkB;AACtD,qBAAiB,OAAO;AACxB,gCAA4B,OAAO;AAAA,EACrC,OAAO;AACL,eAAW;AAAA,MACT,MAAM,QAAQ;AAAA,QACZ,MAAM,KAAK;AAAA,UACT,GAAG,KAAK;AAAA,UACR,YAAY;AAAA,QACd,CAAC;AAAA,MACH;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,aAAW,+BAA+B,QAAQ;AAClD,QAAM,eACJ,KAAK,YAAY,QAAQ,QAAQ,KAAK,YAAY,MAAM,QAAQ,eAAe,WAAW,IACtF,aACA;AACN,MAAI,oBAAoB;AACtB,UAAM,UAAU,aAAa,QAAQ;AACrC,gBAAY,YAAY;AAAA,MACtB,MAAM;AAAA,MACN,WAAW,KAAK;AAAA,MAChB,YAAY,SAAS;AAAA,MACrB,YAAY;AAAA,QACV,OAAO;AAAA,QACP,UAAU;AAAA,QACV,MAAM,oBAAoB,OAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,YAAY,QAAQ,EAAE,CAAC,CAAC;AAAA,QAC9E;AAAA,MACF;AAAA,IACF,CAAoC;AACpC,eAAW;AAAA,EACb;AAEA,MAAI,UAAU;AACZ,UAAM,YAAY,uBAAuB,UAAU,cAAc,CAAC,GAAG,cAAc;AACnF,eAAW,UAAU;AACrB,yBAAqB,UAAU;AAC/B,oBAAgB,UAAU;AAC1B,0BAAsB,UAAU;AAAA,EAClC;AAEA,QAAM,eAAe,YAAY,IAAI,IAAI;AACzC,YAAU,MAAM,+BAA+B;AAAA,IAC7C,OAAO,KAAK;AAAA,IACZ,WAAW,UAAU;AAAA,IACrB,iBAAiB,kBAAkB;AAAA,IACnC,UAAU,SAAS;AAAA,IACnB,aAAa,YAAY,UAAU;AAAA,IACnC,cAAc,8BAA8B;AAAA,IAC5C,eAAe,8BAA8B;AAAA,IAC7C,gBAAgB,eAAe;AAAA,IAC/B,aAAa,KAAK,MAAM,YAAY;AAAA,EACtC,CAAC;AAED,QAAM,oBAAoB,YAAY,IAAI;AAC1C,QAAM,qBAAqB,gCAAgC;AAC3D,QAAM,uBAAuB,gBACzB,IAAI,IAAI,cAAc,IAAI,CAAC,SAAS,UAAU,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC,IAClE;AACJ,aAAW;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBACI,CAAC,eAAe;AACd,UAAI,iBAAiB;AACrB,UAAI,WAAW,UAAU,gBAAgB,iBAAiB,sBAAsB;AAC9E,YAAI,kBAAkB;AACtB,mBAAW,EAAE,QAAQ,KAAK,WAAW,SAAS;AAC5C,gBAAM,QAAQ,qBAAqB,IAAI,QAAQ,EAAE;AACjD,cAAI,SAAS,QAAQ,QAAQ,gBAAiB,mBAAkB;AAAA,QAClE;AACA,YAAI,kBAAkB,qBAAqB;AACzC,gCAAsB;AACtB,2BAAiB;AAAA,YACf,GAAG;AAAA,YACH,gBAAgB,cAAc,eAAe,GAAG;AAAA,UAClD;AAAA,QACF;AAAA,MACF;AACA,kBAAY,YAAY;AAAA,QACtB,MAAM;AAAA,QACN,WAAW,KAAK;AAAA,QAChB,YAAY,SAAS;AAAA,QACrB,YAAY;AAAA,MACd,CAAoC;AAAA,IACtC,IACA;AAAA,IACJ;AAAA,IACA,CAAC,gBAAgB;AACf,yBAAmB,WAAW;AAC9B,0BAAoB,oBAAoB,WAAW;AACnD,gBAAU,MAAM,0CAA0C;AAAA,QACxD,OAAO,KAAK;AAAA,QACZ,OAAO,mBAAmB;AAAA,QAC1B,UAAU,YAAY;AAAA,QACtB,YAAY,YAAY;AAAA,QACxB,gBAAgB,YAAY;AAAA,QAC5B,iBAAiB,YAAY;AAAA,QAC7B,wBAAwB,YAAY;AAAA,QACpC,qBAAqB,kBAAkB,YAAY,gBAAgB;AAAA,QACnE,6BAA6B,YAAY;AAAA,QACzC,0BAA0B,kBAAkB,YAAY,qBAAqB;AAAA,MAC/E,CAAC;AAAA,IACH;AAAA,EACF;AACA,QAAM,uBAAuB,YAAY,IAAI,IAAI;AACjD,QAAM,sBAAsB,KAAK;AAAA,IAC/B;AAAA,IACA,uBACE,mBAAmB,mBACnB,mBAAmB;AAAA,EACvB;AACA,YAAU,MAAM,iCAAiC;AAAA,IAC/C,OAAO,KAAK;AAAA,IACZ,WAAW,UAAU;AAAA,IACrB,iBAAiB,gBAAgB,mBAAmB,GAAG;AAAA,IACvD,UAAU,SAAS;AAAA,IACnB,oBAAoB,mBAAmB;AAAA,IACvC,SAAS,mBAAmB;AAAA,IAC5B,YAAY,mBAAmB;AAAA,IAC/B,gBAAgB,mBAAmB;AAAA,IACnC,iBAAiB,mBAAmB;AAAA,IACpC,wBAAwB,mBAAmB;AAAA,IAC3C,qBAAqB,kBAAkB,mBAAmB,gBAAgB;AAAA,IAC1E,yBAAyB;AAAA,MACvB,mBAAmB,sBAAsB,IACrC,mBAAmB,mBAAmB,mBAAmB,sBACzD;AAAA,IACN;AAAA,IACA,6BAA6B,mBAAmB;AAAA,IAChD,0BAA0B,kBAAkB,mBAAmB,qBAAqB;AAAA,IACpF,8BAA8B;AAAA,MAC5B,mBAAmB,2BAA2B,IAC1C,mBAAmB,wBAAwB,mBAAmB,2BAC9D;AAAA,IACN;AAAA,IACA,uBAAuB,kBAAkB,mBAAmB;AAAA,IAC5D,aAAa,kBAAkB,oBAAoB;AAAA,IACnD,mBAAmB,KAAK,MAAM,YAAY,IAAI,IAAI,SAAS;AAAA,EAC7D,CAAC;AACD,QAAM,WAAW,oBAAoB,OAAO,IAAI,IAAI,SAAS,IAAI,CAAC,YAAY,QAAQ,EAAE,CAAC,CAAC;AAC1F,QAAM,WAAW,qBAAqB,cAAc,QAAQ;AAC5D,QAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA,CAAC,GAAI,cAAc,CAAC,GAAI,GAAG,OAAO,KAAK,SAAS,OAAO,GAAG,GAAG,SAAS,UAAU;AAAA,IAChF;AAAA,EACF;AAEA,WAAS,SAAS;AAAA,IAChB,WAAW,KAAK;AAAA,IAChB,YAAY,SAAS;AAAA,IACrB;AAAA,IACA,MAAM;AAAA,EACR;AACA,kBAAgB,MAAM;AACtB,cAAY,YAAY;AAAA,IACtB,MAAM;AAAA,IACN,WAAW,KAAK;AAAA,IAChB,YAAY,SAAS;AAAA,IACrB,SAAS,KAAK;AAAA,IACd,mBAAmB,KAAK;AAAA,IACxB,MAAM,SAAS;AAAA,IACf,gBAAgB,SAAS;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,YAAY,IAAI,IAAI;AAAA,EAClC,CAAoC;AACtC;AAEA,eAAe,cAAc,MAAkD;AAC7E,QAAM,YAAY,YAAY,IAAI;AAClC,QAAM,kBAAkB,IAAI;AAAA,IAC1B;AAAA,IACA,CAAC,aAAa;AACZ,kBAAY,YAAY;AAAA,QACtB,MAAM;AAAA,QACN,WAAW,KAAK;AAAA,QAChB,YAAY,KAAK,cAAc;AAAA,QAC/B;AAAA,MACF,CAAoC;AAAA,IACtC;AAAA,EACF;AACA,MAAI;AACF,iCAA6B,KAAK,mBAAmB;AACrD,UAAM,IAAI,MAAM,eAAe;AAAA,EACjC,SAAS,OAAO;AACd,oBAAgB,MAAM;AACtB,qBAAiB,MAAM,OAAO,SAAS;AAAA,EACzC,UAAE;AACA,oBAAgB,OAAO;AAAA,EACzB;AACF;AAEA,IAAI,cAAc,QAAQ,QAAQ;AAElC,SAAS,eAAe,MAA4C;AAClE,MAAI,CAAC,eAAgB,OAAM,IAAI,MAAM,gDAAgD;AACrF,QAAM,SAAS,eAAe;AAC9B,MAAI,CAAC,UAAU,OAAO,cAAc,KAAK,WAAW;AAClD,UAAM,IAAI,MAAM,iBAAiB,KAAK,SAAS,yBAAyB;AAAA,EAC1E;AACA,MAAI,eAAe,eAAe,KAAK,cAAc,OAAO,eAAe,KAAK,YAAY;AAC1F,UAAM,IAAI;AAAA,MACR,+CAA+C,eAAe,UAAU,cAAc,KAAK,UAAU;AAAA,IACvG;AAAA,EACF;AACA,iBAAe,WAAW,OAAO;AACjC,iBAAe,OAAO,OAAO;AAC7B,iBAAe,cAAc;AAC7B,iBAAe,SAAS;AAC1B;AAEA,SAAS,iBAAiB,MAAgC,OAAgB,WAAyB;AACjG,cAAY,YAAY;AAAA,IACtB,MAAM;AAAA,IACN,WAAW,KAAK;AAAA,IAChB,YAAY,KAAK;AAAA,IACjB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC5D,YAAY,YAAY,IAAI,IAAI;AAAA,EAClC,CAAoC;AACtC;AAEA,SAAS,aAAa,MAA4C;AAChE,QAAM,YAAY,YAAY,IAAI;AAClC,MAAI;AACF,mBAAe,IAAI;AAAA,EACrB,SAAS,OAAO;AACd,qBAAiB,MAAM,OAAO,SAAS;AAAA,EACzC;AACF;AAEA,SAAS,eAAe,MAAsC;AAC5D,gBAAc,YACX,KAAK,MAAO,KAAK,SAAS,WAAW,aAAa,IAAI,IAAI,cAAc,IAAI,CAAE,EAC9E,MAAM,CAAC,UAAU;AAChB,cAAU,MAAM,qCAAqC;AAAA,MACnD,YAAY,KAAK;AAAA,MACjB,cAAc,KAAK;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACL;AAEA,IAAM,iBAAiB;AACvB,IACE,gBAAgB,SAAS,SACzB,OAAO,eAAe,cAAc,YACpC,OAAO,eAAe,cAAc,YACpC,OAAO,eAAe,wBAAwB,YAC9C,eAAe,aAAa,QAC5B,MAAM,QAAQ,eAAe,gBAAgB,KAC7C,eAAe,QAAQ,MACvB;AACA,iBAAe,cAA6C;AAC9D;AAEA,YAAY,GAAG,WAAW,CAAC,YAAsC;AAC/D,iBAAe,OAAO;AACxB,CAAC;","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":";;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,SAAS,YAAY,kBAAkB;;;ACDhC,IAAM,wBAAN,MAAmC;AAAA,EAMxC,YACmB,YACA,MACA,MAAoB,MAAM,YAAY,IAAI,GAC3D;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAHgB;AAAA,EACA;AAAA,EACA;AAAA,EARX,QAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB;AAAA,EACA,aAAa;AAAA,EAQrB,KAAK,OAAc,OAAqB;AACtC,QAAI,KAAK,UAAU,OAAO;AACxB,WAAK,MAAM;AACX,WAAK,QAAQ;AACb,WAAK,QAAQ,KAAK;AAClB;AAAA,IACF;AAEA,QAAI,KAAK,IAAI,IAAI,KAAK,iBAAiB,KAAK,YAAY;AACtD,WAAK,UAAU;AACf,WAAK,aAAa;AAClB,WAAK,QAAQ,KAAK;AAClB;AAAA,IACF;AAEA,SAAK,UAAU;AACf,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,QAAc;AACZ,QAAI,CAAC,KAAK,WAAY;AACtB,UAAM,UAAU,KAAK;AACrB,SAAK,UAAU;AACf,SAAK,aAAa;AAClB,SAAK,QAAQ,OAAO;AAAA,EACtB;AAAA,EAEA,SAAe;AACb,SAAK,QAAQ;AACb,SAAK,gBAAgB;AACrB,SAAK,UAAU;AACf,SAAK,aAAa;AAAA,EACpB;AAAA,EAEQ,QAAQ,OAAoB;AAClC,SAAK,gBAAgB,KAAK,IAAI;AAC9B,SAAK,KAAK,KAAK;AAAA,EACjB;AACF;;;AClDA,SAAS,yBAAyB;AA0B3B,SAAS,sBAAsB,OAAgD;AACpF,QAAM,OAAyC,CAAC;AAChD,QAAM,iBAA2B,CAAC;AAClC,aAAW,CAAC,IAAI,KAAK,KAAK,OAAO,QAAQ,MAAM,QAAQ,GAAG;AACxD,QAAI,CAAC,kBAAkB,MAAM,aAAa,EAAE,GAAG,KAAK,EAAG,MAAK,EAAE,IAAI;AAAA,EACpE;AACA,aAAW,MAAM,OAAO,KAAK,MAAM,YAAY,GAAG;AAChD,QAAI,CAAC,OAAO,OAAO,MAAM,UAAU,EAAE,EAAG,gBAAe,KAAK,EAAE;AAAA,EAChE;AAEA,QAAM,OAAO,4BAA4B,MAAM,kBAAkB,MAAM,UAAU;AAAA,IAC/E,qBAAqB,CAAC,GAAI,MAAM,cAAc,CAAC,GAAI,GAAG,OAAO,KAAK,IAAI,GAAG,GAAG,cAAc;AAAA,IAC1F,cAAc,MAAM;AAAA,IACpB,2BAA2B,MAAM;AAAA,EACnC,CAAC;AACD,SAAO;AAAA,IACL,SAAS,KAAK;AAAA,IACd,mBAAmB,KAAK;AAAA,IACxB;AAAA,IACA;AAAA,EACF;AACF;;;ACnCO,SAAS,oBACd,WAC2C;AAC3C,SAAO,UAAU,SAAS;AAC5B;AAEO,SAAS,uBAAuB,WAA0C;AAC/E,SAAO,gBAAgB,aAAa,UAAU,eAAe;AAC/D;AAEO,SAAS,uBAAuB,WAAkD;AACvF,UAAQ,UAAU,MAAM;AAAA,IACtB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;;;AHgGA,SAAS,uBACP,UACA,YACA,QACmB;AACnB,QAAM,kBAAkB,aAAa,QAAQ;AAC7C,QAAM,cAAc,SAChB,gBAAgB,UAAU,CAAC,YAAY,QAAQ,UAAU,cAAc,MAAM,IAC7E;AACJ,QAAM,qBAAqB,oBAAI,IAAY;AAC3C,QAAM,aAAa,eAAe,IAAI,cAAc,IAAI;AAExD,WAAS,QAAQ,YAAY,QAAQ,gBAAgB,QAAQ,SAAS,GAAG;AACvE,uBAAmB,IAAI,gBAAgB,KAAK,EAAG,UAAU,SAAS;AAAA,EACpE;AAEA,aAAW,aAAa,WAAY,oBAAmB,IAAI,SAAS;AAIpE,WAAS,QAAQ,GAAG,SAAS,aAAa,SAAS,GAAG;AACpD,UAAM,UAAU,gBAAgB,KAAK;AACrC,QAAI,oBAAoB,OAAO,EAAG,oBAAmB,IAAI,QAAQ,UAAU,SAAS;AAAA,EACtF;AAEA,SAAO,EAAE,iBAAiB,oBAAoB,YAAY;AAC5D;AAOA,IAAM,gBAAgB;AACtB,IAAM,sBAAsB;AAC5B,IAAM,uBAAuB;AAM7B,SAAS,kCAA6D;AACpE,SAAO;AAAA,IACL,SAAS;AAAA,IACT,UAAU;AAAA,IACV,WAAW;AAAA,IACX,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,qBAAqB;AAAA,IACrB,kBAAkB;AAAA,IAClB,0BAA0B;AAAA,IAC1B,uBAAuB;AAAA,EACzB;AACF;AAEA,SAAS,oBAAoB,QAAmC,QAAgC;AAC9F,SAAO,YAAY,OAAO;AAC1B,SAAO,aAAa,OAAO;AAC3B,SAAO,iBAAiB,OAAO;AAC/B,SAAO,kBAAkB,OAAO;AAChC,SAAO,uBAAuB,OAAO;AACrC,SAAO,oBAAoB,OAAO;AAClC,SAAO,4BAA4B,OAAO;AAC1C,SAAO,yBAAyB,OAAO;AACzC;AAEA,SAAS,kBAAkB,OAAuB;AAChD,SAAO,KAAK,MAAM,QAAQ,GAAG,IAAI;AACnC;AAEA,SAAS,UAAU,SAAsB,KAAsB;AAC7D,SAAO,OAAO,QAAQ,gBAAgB,QAAQ,iBAAiB;AACjE;AAMO,SAAS,iBACd,OACA,UACA,YACA,cACA,oBACA,UACe;AACf,QAAM,UAAU,aAAa,+BAA+B,QAAQ,CAAC;AAErE,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,UAAU,QAAQ;AAAA,IACtB,CAAC,aACE,CAAC,sBAAsB,mBAAmB,IAAI,QAAQ,UAAU,SAAS,MAC1E,UAAU,SAAS,GAAG;AAAA,EAC1B;AACA,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,MAAI,iBAAiB;AACrB,QAAM,iBAAiB,CAAC,WAAmB,UAAwB;AACjE,UAAMA,OAAM,YAAY,IAAI;AAC5B,QAAI,cAAc,KAAK,cAAc,SAASA,OAAM,iBAAiB,IAAK;AAC1E,qBAAiBA;AACjB,iBAAa;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,UAAU,QAAQ;AAAA,IACpB,CAAC;AAAA,EACH;AACA,iBAAe,GAAG,QAAQ,MAAM;AAEhC,QAAM,gBAAgB,IAAI;AAAA,IACxB,QAAQ,IAAI,CAAC,SAAS,UAAU,CAAC,QAAQ,UAAU,WAAW,KAAK,CAAC;AAAA,EACtE;AACA,QAAM,aAAa,oBAAI,IAAyB;AAChD,WAAS,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS,qBAAqB;AACxE,UAAM,QAAQ,QAAQ,MAAM,OAAO,QAAQ,mBAAmB;AAC9D,UAAM,eAAe,sBAAsB,OAAO,OAAO,CAAC,cAAc;AACtE,qBAAe,QAAQ,WAAW,QAAQ,MAAM;AAAA,IAClD,CAAC;AACD,QAAI,aAAa,OAAQ,YAAW,aAAa,MAAM;AACvD,UAAM,cAAc,aAAa;AACjC,eAAW,WAAW,YAAa,YAAW,IAAI,QAAQ,UAAU,WAAW,OAAO;AAEtF,mBAAe;AAAA,MACb,OAAO;AAAA,MACP,SAAS,YAAY,IAAI,CAAC,aAAa;AAAA,QACrC;AAAA,QACA,WAAW,cAAc,IAAI,QAAQ,UAAU,SAAS,KAAK;AAAA,MAC/D,EAAE;AAAA,MACF,MAAM;AAAA,QACJ;AAAA,QACA,IAAI,IAAI,YAAY,IAAI,CAAC,YAAY,QAAQ,UAAU,SAAS,CAAC;AAAA,MACnE;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO,QAAQ,IAAI,CAAC,YAAY,WAAW,IAAI,QAAQ,UAAU,SAAS,KAAK,OAAO;AACxF;AAEA,IAAI,iBAAwC;AAE5C,SAAS,YAAY,MAAmD;AACtE,QAAM,aAAa,KAAK,cAAc;AACtC,QAAM,cAAc,MAAM,QAAQ,KAAK,gBAAgB;AACvD,QAAM,UAAU,KAAK,QAAQ;AAC7B,MAAI,gBAAgB;AAClB,UAAM,IAAI,MAAM,qDAAqD;AAEvE,MAAI,eAAe,SAAS;AAC1B,QAAI,eAAgB,OAAM,IAAI,MAAM,qDAAqD;AACzF,UAAM,QAAQ,uBAAuB,EAAE,KAAK,CAAC,SAAS,KAAK,SAAS,KAAK,SAAS;AAClF,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,kBAAkB,KAAK,SAAS,EAAE;AAC9D,qBAAiB;AAAA,MACf,WAAW,KAAK;AAAA,MAChB;AAAA,MACA;AAAA,MACA,UAAU,KAAK;AAAA,MACf,MAAM,KAAK;AAAA,MACX,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,CAAC,eAAgB,OAAM,IAAI,MAAM,iDAAiD;AACtF,MAAI,eAAe,cAAc,KAAK,WAAW;AAC/C,UAAM,IAAI,MAAM,mCAAmC,eAAe,SAAS,EAAE;AAAA,EAC/E;AACA,MAAI,eAAe,eAAe,YAAY;AAC5C,UAAM,IAAI;AAAA,MACR,wCAAwC,eAAe,UAAU,cAAc,UAAU;AAAA,IAC3F;AAAA,EACF;AACA,MAAI,eAAe,QAAQ;AACzB,UAAM,IAAI,MAAM,iBAAiB,eAAe,OAAO,SAAS,qBAAqB;AAAA,EACvF;AAEA,iBAAe,MAAM,wBAAwB,eAAe,IAAI;AAChE,SAAO;AACT;AAEA,eAAe,IACb,MACA,iBACe;AACf,QAAM,YAAY,YAAY,IAAI;AAClC,QAAM,WAAW,YAAY,IAAI;AACjC,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,mBAAmB,SAAS;AAClC,QAAM,eAAe,SAAS;AAC9B,QAAM,YAAY,KAAK;AACvB,QAAM,WAAW,oBAAoB,SAAS;AAC9C,QAAM,WAAW,cAAc,MAAM,qBAAqB,uBAAuB,SAAS,CAAC;AAC3F,QAAM,qBAAqB,uBAAuB,SAAS;AAC3D,QAAM,iBAAiB,WAAW,UAAU,SAAS;AAErD,YAAU,MAAM,+BAA+B;AAAA,IAC7C,OAAO,KAAK;AAAA,IACZ,WAAW,UAAU;AAAA,IACrB,iBAAiB,kBAAkB;AAAA,IACnC,mBAAmB,iBAAiB;AAAA,EACtC,CAAC;AAED,QAAM,iBAAiB,CAAC,aAAsC;AAC5D,oBAAgB,KAAK,UAAU,SAAS,SAAS,UAAU;AAAA,EAC7D;AAEA,MAAI,CAAC,MAAM,YAAY,GAAG;AACxB,cAAU,KAAK,yCAAyC;AAAA,MACtD,OAAO,KAAK;AAAA,MACZ,WAAW,UAAU;AAAA,IACvB,CAAC;AACD,UAAM,IAAI,gCAAgC,KAAK,SAAS;AAAA,EAC1D;AAEA,MAAI,SAAS,SAAS,qBAAqB;AACzC,UAAM,IAAI,MAAM,mDAAmD,MAAM,IAAI,gBAAgB;AAAA,EAC/F;AACA,QAAM,YAAY;AAAA,IAChB;AAAA,IACA;AAAA,IACA,EAAE,UAAU,kBAAkB,MAAM,aAAa;AAAA,IACjD,EAAE,GAAG,KAAK,aAAa,YAAY,eAAe;AAAA,EACpD;AACA,MAAI,WAAW,UAAU;AACzB,QAAM,aAAa,UAAU;AAC7B,QAAM,iBAAiB,UAAU;AACjC,QAAM,4BAA4B,UAAU;AAC5C,MAAI,qBACF,UAAU,uBAAuB,SAAY,SAAY,IAAI,IAAI,UAAU,kBAAkB;AAC/F,MAAI;AACJ,MAAI,sBAAsB;AAC1B,QAAM,+BAA+B,UAAU,wBAC3C;AAAA,IACE,aAAa,UAAU,sBAAsB;AAAA,IAC7C,cAAc,UAAU,sBAAsB;AAAA,IAC9C,eAAe,UAAU,sBAAsB,OAAO;AAAA,IACtD,QAAQ,UAAU,sBAAsB,OAAO;AAAA,IAC/C,SAAS,UAAU,sBAAsB,OAAO;AAAA,IAChD,cAAc,UAAU,sBAAsB,OAAO;AAAA,IACrD,gBAAgB,UAAU,sBAAsB,OAAO;AAAA,EACzD,IACA;AAEJ,aAAW,+BAA+B,QAAQ;AAClD,QAAM,eAAe,UAAU;AAC/B,MAAI,oBAAoB;AACtB,UAAM,UAAU,aAAa,QAAQ;AACrC,gBAAY,YAAY;AAAA,MACtB,MAAM;AAAA,MACN,WAAW,KAAK;AAAA,MAChB,YAAY,SAAS;AAAA,MACrB,YAAY;AAAA,QACV,OAAO;AAAA,QACP,UAAU;AAAA,QACV,MAAM;AAAA,UACJ;AAAA,UACA,IAAI,IAAI,QAAQ,IAAI,CAAC,YAAY,QAAQ,UAAU,SAAS,CAAC;AAAA,QAC/D;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAoC;AACpC,eAAW;AAAA,EACb;AAEA,MAAI,UAAU;AACZ,UAAM,YAAY,uBAAuB,UAAU,cAAc,CAAC,GAAG,cAAc;AACnF,eAAW,UAAU;AACrB,yBAAqB,UAAU;AAC/B,oBAAgB,UAAU;AAC1B,0BAAsB,UAAU;AAAA,EAClC;AAEA,QAAM,eAAe,YAAY,IAAI,IAAI;AACzC,YAAU,MAAM,+BAA+B;AAAA,IAC7C,OAAO,KAAK;AAAA,IACZ,WAAW,UAAU;AAAA,IACrB,iBAAiB,kBAAkB;AAAA,IACnC,UAAU,SAAS;AAAA,IACnB,aAAa,YAAY,UAAU;AAAA,IACnC,cAAc,8BAA8B;AAAA,IAC5C,eAAe,8BAA8B;AAAA,IAC7C,uBAAuB,kBAAkB,8BAA8B,iBAAiB,CAAC;AAAA,IACzF,gBAAgB,kBAAkB,8BAA8B,UAAU,CAAC;AAAA,IAC3E,iBAAiB,kBAAkB,8BAA8B,WAAW,CAAC;AAAA,IAC7E,iBAAiB,8BAA8B;AAAA,IAC/C,mBAAmB,8BAA8B;AAAA,IACjD,gBAAgB,eAAe;AAAA,IAC/B,aAAa,KAAK,MAAM,YAAY;AAAA,EACtC,CAAC;AAED,QAAM,oBAAoB,YAAY,IAAI;AAC1C,QAAM,qBAAqB,gCAAgC;AAC3D,QAAM,uBAAuB,gBACzB,IAAI,IAAI,cAAc,IAAI,CAAC,SAAS,UAAU,CAAC,QAAQ,UAAU,WAAW,KAAK,CAAC,CAAC,IACnF;AACJ,aAAW;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBACI,CAAC,eAAe;AACd,UAAI,iBAAiB;AACrB,UAAI,WAAW,UAAU,gBAAgB,iBAAiB,sBAAsB;AAC9E,YAAI,kBAAkB;AACtB,mBAAW,EAAE,QAAQ,KAAK,WAAW,SAAS;AAC5C,gBAAM,QAAQ,qBAAqB,IAAI,QAAQ,UAAU,SAAS;AAClE,cAAI,SAAS,QAAQ,QAAQ,gBAAiB,mBAAkB;AAAA,QAClE;AACA,YAAI,kBAAkB,qBAAqB;AACzC,gCAAsB;AACtB,2BAAiB;AAAA,YACf,GAAG;AAAA,YACH,gBAAgB,cAAc,eAAe,GAAG,UAAU;AAAA,UAC5D;AAAA,QACF;AAAA,MACF;AACA,kBAAY,YAAY;AAAA,QACtB,MAAM;AAAA,QACN,WAAW,KAAK;AAAA,QAChB,YAAY,SAAS;AAAA,QACrB,YAAY;AAAA,MACd,CAAoC;AAAA,IACtC,IACA;AAAA,IACJ;AAAA,IACA,CAAC,gBAAgB;AACf,yBAAmB,WAAW;AAC9B,0BAAoB,oBAAoB,WAAW;AACnD,gBAAU,MAAM,0CAA0C;AAAA,QACxD,OAAO,KAAK;AAAA,QACZ,OAAO,mBAAmB;AAAA,QAC1B,UAAU,YAAY;AAAA,QACtB,YAAY,YAAY;AAAA,QACxB,gBAAgB,YAAY;AAAA,QAC5B,iBAAiB,YAAY;AAAA,QAC7B,wBAAwB,YAAY;AAAA,QACpC,qBAAqB,kBAAkB,YAAY,gBAAgB;AAAA,QACnE,6BAA6B,YAAY;AAAA,QACzC,0BAA0B,kBAAkB,YAAY,qBAAqB;AAAA,MAC/E,CAAC;AAAA,IACH;AAAA,EACF;AACA,QAAM,uBAAuB,YAAY,IAAI,IAAI;AACjD,QAAM,sBAAsB,KAAK;AAAA,IAC/B;AAAA,IACA,uBACE,mBAAmB,mBACnB,mBAAmB;AAAA,EACvB;AACA,YAAU,MAAM,iCAAiC;AAAA,IAC/C,OAAO,KAAK;AAAA,IACZ,WAAW,UAAU;AAAA,IACrB,iBAAiB,gBAAgB,mBAAmB,GAAG,UAAU;AAAA,IACjE,UAAU,SAAS;AAAA,IACnB,oBAAoB,mBAAmB;AAAA,IACvC,SAAS,mBAAmB;AAAA,IAC5B,YAAY,mBAAmB;AAAA,IAC/B,gBAAgB,mBAAmB;AAAA,IACnC,iBAAiB,mBAAmB;AAAA,IACpC,wBAAwB,mBAAmB;AAAA,IAC3C,qBAAqB,kBAAkB,mBAAmB,gBAAgB;AAAA,IAC1E,yBAAyB;AAAA,MACvB,mBAAmB,sBAAsB,IACrC,mBAAmB,mBAAmB,mBAAmB,sBACzD;AAAA,IACN;AAAA,IACA,6BAA6B,mBAAmB;AAAA,IAChD,0BAA0B,kBAAkB,mBAAmB,qBAAqB;AAAA,IACpF,8BAA8B;AAAA,MAC5B,mBAAmB,2BAA2B,IAC1C,mBAAmB,wBAAwB,mBAAmB,2BAC9D;AAAA,IACN;AAAA,IACA,uBAAuB,kBAAkB,mBAAmB;AAAA,IAC5D,aAAa,kBAAkB,oBAAoB;AAAA,IACnD,mBAAmB,KAAK,MAAM,YAAY,IAAI,IAAI,SAAS;AAAA,EAC7D,CAAC;AACD,QAAM,WAAW;AAAA,IACf;AAAA,IACA,IAAI,IAAI,SAAS,IAAI,CAAC,YAAY,QAAQ,UAAU,SAAS,CAAC;AAAA,EAChE;AACA,QAAM,QAAQ,sBAAsB;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,WAAS,SAAS;AAAA,IAChB,WAAW,KAAK;AAAA,IAChB,YAAY,SAAS;AAAA,IACrB;AAAA,IACA,MAAM;AAAA,EACR;AACA,kBAAgB,MAAM;AACtB,cAAY,YAAY;AAAA,IACtB,MAAM;AAAA,IACN,WAAW,KAAK;AAAA,IAChB,YAAY,SAAS;AAAA,IACrB,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,YAAY,IAAI,IAAI;AAAA,EAClC,CAAoC;AACtC;AAEA,eAAe,cAAc,MAAkD;AAC7E,QAAM,YAAY,YAAY,IAAI;AAClC,QAAM,kBAAkB,IAAI;AAAA,IAC1B;AAAA,IACA,CAAC,aAAa;AACZ,kBAAY,YAAY;AAAA,QACtB,MAAM;AAAA,QACN,WAAW,KAAK;AAAA,QAChB,YAAY,KAAK,cAAc;AAAA,QAC/B;AAAA,MACF,CAAoC;AAAA,IACtC;AAAA,EACF;AACA,MAAI;AACF,iCAA6B,KAAK,mBAAmB;AACrD,UAAM,IAAI,MAAM,eAAe;AAAA,EACjC,SAAS,OAAO;AACd,oBAAgB,MAAM;AACtB,qBAAiB,MAAM,OAAO,SAAS;AAAA,EACzC,UAAE;AACA,oBAAgB,OAAO;AAAA,EACzB;AACF;AAEA,IAAI,cAAc,QAAQ,QAAQ;AAElC,SAAS,eAAe,MAA4C;AAClE,MAAI,CAAC,eAAgB,OAAM,IAAI,MAAM,gDAAgD;AACrF,QAAM,SAAS,eAAe;AAC9B,MAAI,CAAC,UAAU,OAAO,cAAc,KAAK,WAAW;AAClD,UAAM,IAAI,MAAM,iBAAiB,KAAK,SAAS,yBAAyB;AAAA,EAC1E;AACA,MAAI,eAAe,eAAe,KAAK,cAAc,OAAO,eAAe,KAAK,YAAY;AAC1F,UAAM,IAAI;AAAA,MACR,+CAA+C,eAAe,UAAU,cAAc,KAAK,UAAU;AAAA,IACvG;AAAA,EACF;AACA,iBAAe,WAAW,OAAO;AACjC,iBAAe,OAAO,OAAO;AAC7B,iBAAe,cAAc;AAC7B,iBAAe,SAAS;AAC1B;AAEA,SAAS,iBAAiB,MAAgC,OAAgB,WAAyB;AACjG,QAAM,YAAY,iBAAiB,kCAAkC,MAAM,OAAO;AAClF,cAAY,YAAY;AAAA,IACtB,MAAM;AAAA,IACN,WAAW,KAAK;AAAA,IAChB,YAAY,KAAK;AAAA,IACjB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC5D,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IACjC,YAAY,YAAY,IAAI,IAAI;AAAA,EAClC,CAAoC;AACtC;AAEA,SAAS,aAAa,MAA4C;AAChE,QAAM,YAAY,YAAY,IAAI;AAClC,MAAI;AACF,mBAAe,IAAI;AAAA,EACrB,SAAS,OAAO;AACd,qBAAiB,MAAM,OAAO,SAAS;AAAA,EACzC;AACF;AAEA,SAAS,eAAe,MAAsC;AAC5D,gBAAc,YACX,KAAK,MAAO,KAAK,SAAS,WAAW,aAAa,IAAI,IAAI,cAAc,IAAI,CAAE,EAC9E,MAAM,CAAC,UAAU;AAChB,cAAU,MAAM,qCAAqC;AAAA,MACnD,YAAY,KAAK;AAAA,MACjB,cAAc,KAAK;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACL;AAEA,IAAM,iBAAiB;AACvB,IACE,gBAAgB,SAAS,SACzB,OAAO,eAAe,cAAc,YACpC,OAAO,eAAe,cAAc,YACpC,OAAO,eAAe,wBAAwB,YAC9C,eAAe,aAAa,QAC5B,MAAM,QAAQ,eAAe,gBAAgB,KAC7C,eAAe,QAAQ,MACvB;AACA,iBAAe,cAA6C;AAC9D;AAEA,YAAY,GAAG,WAAW,CAAC,YAAsC;AAC/D,iBAAe,OAAO;AACxB,CAAC;","names":["now"]}
|