codesesh 0.17.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +6 -4
  2. package/dist/{chunk-7APNDHQ6.js → chunk-G2BTNW3C.js} +2262 -495
  3. package/dist/chunk-G2BTNW3C.js.map +1 -0
  4. package/dist/{chunk-A4U2SMJJ.js → chunk-KD3DGWZY.js} +20 -12
  5. package/dist/chunk-KD3DGWZY.js.map +1 -0
  6. package/dist/{dist-KEPJFHOC.js → dist-ALXOBKV2.js} +26 -4
  7. package/dist/index.js +382 -114
  8. package/dist/index.js.map +1 -1
  9. package/dist/scan-refresh-worker.js +243 -24
  10. package/dist/scan-refresh-worker.js.map +1 -1
  11. package/dist/search-index-worker.js +73 -39
  12. package/dist/search-index-worker.js.map +1 -1
  13. package/dist/smart-tag-worker.js +2 -2
  14. package/dist/web/assets/AgentIcon-CEj7HO1m.js +1 -0
  15. package/dist/web/assets/BookmarkButton-DLEnIyeE.js +1 -0
  16. package/dist/web/assets/Dashboard-DUG0IFcy.js +39 -0
  17. package/dist/web/assets/DialogTitle-Dv6DQPIb.js +1 -0
  18. package/dist/web/assets/InteractiveReceipt-xnRqJvfd.js +1 -0
  19. package/dist/web/assets/PrismHighlighter-C7OfXHq2.js +6 -0
  20. package/dist/web/assets/Projects-BMaZc6J5.js +1 -0
  21. package/dist/web/assets/SearchFilterBar-iP6pzlZo.js +1 -0
  22. package/dist/web/assets/SearchResultsPanel-RuiLPkbP.js +1 -0
  23. package/dist/web/assets/SessionDetail-De1Wl3mu.js +54 -0
  24. package/dist/web/assets/index-B-CV7pFu.css +2 -0
  25. package/dist/web/assets/index-CQI8F_8X.js +1930 -0
  26. package/dist/web/assets/index.dom-CCLJ9_FR.js +1 -0
  27. package/dist/web/assets/jsx-runtime-n5LQ9ujS.js +1 -0
  28. package/dist/web/assets/session-indexes-BuxBafvh.js +4 -0
  29. package/dist/web/assets/session-title-CNhapdPJ.js +1 -0
  30. package/dist/web/assets/useTheme-CwDcVdGz.js +1 -0
  31. package/dist/web/assets/utils-B6KiDbIe.js +1 -0
  32. package/dist/web/index.html +10 -7
  33. package/package.json +3 -3
  34. package/dist/chunk-7APNDHQ6.js.map +0 -1
  35. package/dist/chunk-A4U2SMJJ.js.map +0 -1
  36. package/dist/web/assets/index-B076CRkD.js +0 -109
  37. package/dist/web/assets/index-CWNbVhet.css +0 -2
  38. package/dist/web/assets/markdown-dR4kAewZ.js +0 -14
  39. package/dist/web/assets/react-D9s532MZ.js +0 -1821
  40. package/dist/web/assets/rolldown-runtime-QTnfLwEv.js +0 -1
  41. package/dist/web/assets/syntax-mZXQuVcd.js +0 -6
  42. package/dist/web/assets/vendor-i9U7_fNF.js +0 -41
  43. /package/dist/{dist-KEPJFHOC.js.map → dist-ALXOBKV2.js.map} +0 -0
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-A4U2SMJJ.js";
2
+ import {
3
+ appLogger
4
+ } from "./chunk-KD3DGWZY.js";
3
5
  import {
4
6
  FileSystemSessionSource,
5
7
  attachMissingProjectIdentities,
@@ -8,8 +10,9 @@ import {
8
10
  createRegisteredAgents,
9
11
  diffSessionSources,
10
12
  ensureSessionTagsSync,
11
- sessionSignature
12
- } from "./chunk-7APNDHQ6.js";
13
+ sessionSignature,
14
+ sortSessions
15
+ } from "./chunk-G2BTNW3C.js";
13
16
 
14
17
  // src/scan-refresh-worker.ts
15
18
  import { parentPort, workerData } from "worker_threads";
@@ -25,7 +28,26 @@ function computeCacheMetaDiff(previous, next) {
25
28
  }
26
29
  return { changes, removedIds };
27
30
  }
28
- function syncAgentSources(agent, cachedSessions, cachedMeta, windowOptions) {
31
+ function hasStaleSmartTags(session) {
32
+ const sourceUpdatedAt = session.time_updated ?? session.time_created;
33
+ return !Array.isArray(session.smart_tags) || session.smart_tags_source_updated_at !== sourceUpdatedAt;
34
+ }
35
+ function selectBackfillSessions(sessions, changedIds, cursor) {
36
+ const orderedSessions = sortSessions(sessions);
37
+ const cursorIndex = cursor ? orderedSessions.findIndex((session) => session.id === cursor) : -1;
38
+ const finalizeSessionIds = /* @__PURE__ */ new Set();
39
+ const startIndex = cursorIndex >= 0 ? cursorIndex + 1 : 0;
40
+ for (let index = startIndex; index < orderedSessions.length; index += 1) {
41
+ finalizeSessionIds.add(orderedSessions[index].id);
42
+ }
43
+ for (const changedId of changedIds) finalizeSessionIds.add(changedId);
44
+ for (let index = 0; index <= cursorIndex; index += 1) {
45
+ const session = orderedSessions[index];
46
+ if (hasStaleSmartTags(session)) finalizeSessionIds.add(session.id);
47
+ }
48
+ return { orderedSessions, finalizeSessionIds, cursorIndex };
49
+ }
50
+ function syncAgentSources(agent, cachedSessions, cachedMeta, windowOptions, onProgress) {
29
51
  const sessionMap = new Map(cachedSessions.map((session) => [session.id, session]));
30
52
  const sourceRefs = agent.listSessionSources(windowOptions);
31
53
  const sourceById = new Map(sourceRefs.map((source) => [source.sessionId, source]));
@@ -35,35 +57,103 @@ function syncAgentSources(agent, cachedSessions, cachedMeta, windowOptions) {
35
57
  cachedMeta,
36
58
  windowOptions
37
59
  );
38
- for (const sessionId of changedIds) {
60
+ const rescanIds = agent.expandChangedSessionIds?.(
61
+ [.../* @__PURE__ */ new Set([...changedIds, ...removedIds])],
62
+ sourceRefs
63
+ ) ?? [.../* @__PURE__ */ new Set([...changedIds, ...removedIds])];
64
+ const isWindowed = windowOptions?.from != null || windowOptions?.to != null;
65
+ const finalizeSessionIds = isWindowed ? [...rescanIds] : sourceRefs.map((source) => source.sessionId);
66
+ rescanIds.forEach((sessionId, index) => {
39
67
  const source = sourceById.get(sessionId);
40
- if (!source) continue;
68
+ if (!source) return;
41
69
  const next = agent.scanSessionSource(source.sourcePath);
42
70
  if (next) {
43
71
  sessionMap.set(next.id, next);
44
72
  } else {
45
73
  sessionMap.delete(sessionId);
46
74
  }
47
- }
75
+ onProgress?.({ total: rescanIds.length, processed: index + 1, sessions: sessionMap.size });
76
+ });
48
77
  for (const sessionId of removedIds) sessionMap.delete(sessionId);
49
78
  return {
50
79
  sessions: [...sessionMap.values()],
51
- changedIds: [.../* @__PURE__ */ new Set([...changedIds, ...removedIds])]
80
+ changedIds: rescanIds,
81
+ finalizeSessionIds,
82
+ sourceCount: sourceRefs.length,
83
+ removedCount: removedIds.length
52
84
  };
53
85
  }
54
86
  var TAG_SETTLE_MS = 6e4;
87
+ var TAG_CHECKPOINT_SIZE = 32;
88
+ function createSessionFinalizationTiming() {
89
+ return {
90
+ batches: 0,
91
+ sessions: 0,
92
+ cacheHits: 0,
93
+ staleSessions: 0,
94
+ failedSessions: 0,
95
+ getSessionDataCalls: 0,
96
+ getSessionDataMs: 0,
97
+ classifySessionTagsCalls: 0,
98
+ classifySessionTagsMs: 0
99
+ };
100
+ }
101
+ function addSessionTagTiming(target, source) {
102
+ target.sessions += source.sessions;
103
+ target.cacheHits += source.cacheHits;
104
+ target.staleSessions += source.staleSessions;
105
+ target.failedSessions += source.failedSessions;
106
+ target.getSessionDataCalls += source.getSessionDataCalls;
107
+ target.getSessionDataMs += source.getSessionDataMs;
108
+ target.classifySessionTagsCalls += source.classifySessionTagsCalls;
109
+ target.classifySessionTagsMs += source.classifySessionTagsMs;
110
+ }
111
+ function roundMilliseconds(value) {
112
+ return Math.round(value * 100) / 100;
113
+ }
55
114
  function isSettled(session, now) {
56
115
  return now - (session.time_updated ?? session.time_created) >= TAG_SETTLE_MS;
57
116
  }
58
- function finalizeSessions(agent, sessions) {
59
- const withIdentity = attachMissingProjectIdentities(sessions);
117
+ function finalizeSessions(agent, sessions, onProgress, onCheckpoint, finalizeSessionIds, onTiming) {
118
+ const ordered = sortSessions(attachMissingProjectIdentities(sessions));
60
119
  const now = Date.now();
61
- const settled = withIdentity.filter((session) => isSettled(session, now));
62
- if (settled.length === 0) return withIdentity;
63
- const taggedById = new Map(
64
- ensureSessionTagsSync(agent, settled).sessions.map((session) => [session.id, session])
120
+ const settled = ordered.filter(
121
+ (session) => (!finalizeSessionIds || finalizeSessionIds.has(session.id)) && isSettled(session, now)
65
122
  );
66
- return withIdentity.map((session) => taggedById.get(session.id) ?? session);
123
+ if (settled.length === 0) return ordered;
124
+ let lastReportedAt = -Infinity;
125
+ const reportProgress = (processed, total) => {
126
+ const now2 = performance.now();
127
+ if (processed !== 0 && processed !== total && now2 - lastReportedAt < 100) return;
128
+ lastReportedAt = now2;
129
+ onProgress?.({
130
+ phase: "finalizing",
131
+ total,
132
+ processed,
133
+ sessions: ordered.length
134
+ });
135
+ };
136
+ reportProgress(0, settled.length);
137
+ const sortIndexById = new Map(ordered.map((session, index) => [session.id, index]));
138
+ const taggedById = /* @__PURE__ */ new Map();
139
+ for (let start = 0; start < settled.length; start += TAG_CHECKPOINT_SIZE) {
140
+ const batch = settled.slice(start, start + TAG_CHECKPOINT_SIZE);
141
+ const taggedResult = ensureSessionTagsSync(agent, batch, (processed) => {
142
+ reportProgress(start + processed, settled.length);
143
+ });
144
+ if (taggedResult.timing) onTiming?.(taggedResult.timing);
145
+ const taggedBatch = taggedResult.sessions;
146
+ for (const session of taggedBatch) taggedById.set(session.id, session);
147
+ onCheckpoint?.({
148
+ stage: "finalizing",
149
+ changes: taggedBatch.map((session) => ({
150
+ session,
151
+ sortIndex: sortIndexById.get(session.id) ?? 0
152
+ })),
153
+ meta: buildAgentCacheMeta(agent, new Set(taggedBatch.map((session) => session.id)))
154
+ });
155
+ }
156
+ return ordered.map((session) => taggedById.get(session.id) ?? session);
67
157
  }
68
158
  async function run(data) {
69
159
  const startedAt = performance.now();
@@ -71,33 +161,162 @@ async function run(data) {
71
161
  if (!agent) {
72
162
  throw new Error(`Unknown agent: ${data.agentName}`);
73
163
  }
164
+ appLogger.debug("scan.refresh_worker.started", {
165
+ agent: data.agentName,
166
+ source_sync: data.sourceSync ?? false,
167
+ backfill: data.backfill ?? false,
168
+ backfill_cursor: data.backfillCursor ?? void 0,
169
+ changed_ids: data.changedIds?.length ?? 0,
170
+ previous_sessions: data.previousSessions.length
171
+ });
172
+ const reportProgress = (progress) => {
173
+ parentPort?.postMessage({
174
+ type: "progress",
175
+ requestId: data.requestId,
176
+ progress
177
+ });
178
+ };
74
179
  agent.setSessionMetaMap(new Map(Object.entries(data.meta)));
75
180
  const isAvailable = agent.isAvailable();
76
181
  let sessions;
77
182
  let changedIds;
183
+ let finalizeSessionIds;
184
+ let backfillOrder;
185
+ let backfillCursorIndex = -1;
186
+ let sourceSyncDetails;
78
187
  if (!isAvailable) {
79
188
  sessions = [];
80
189
  } else if (data.sourceSync && agent instanceof FileSystemSessionSource) {
81
- const result = syncAgentSources(agent, data.previousSessions, data.meta, data.scanOptions);
190
+ const result = syncAgentSources(
191
+ agent,
192
+ data.previousSessions,
193
+ data.meta,
194
+ data.scanOptions,
195
+ reportProgress
196
+ );
82
197
  sessions = result.sessions;
83
198
  changedIds = result.changedIds;
199
+ finalizeSessionIds = new Set(result.finalizeSessionIds);
200
+ sourceSyncDetails = result;
84
201
  } else if (data.changedIds) {
85
202
  sessions = await Promise.resolve(agent.incrementalScan(data.previousSessions, data.changedIds));
86
203
  } else {
87
204
  sessions = await Promise.resolve(
88
205
  agent.scan({
89
206
  ...data.scanOptions,
90
- onProgress: (progress) => {
91
- parentPort?.postMessage({
92
- type: "progress",
93
- requestId: data.requestId,
94
- progress
95
- });
96
- }
207
+ onProgress: reportProgress
97
208
  })
98
209
  );
99
210
  }
100
- sessions = finalizeSessions(agent, sessions);
211
+ sessions = attachMissingProjectIdentities(sessions);
212
+ if (data.checkpoint) {
213
+ const ordered = sortSessions(sessions);
214
+ parentPort?.postMessage({
215
+ type: "checkpoint",
216
+ requestId: data.requestId,
217
+ checkpoint: {
218
+ stage: "scanned",
219
+ sessions: ordered,
220
+ meta: buildAgentCacheMeta(agent, new Set(ordered.map((session) => session.id)))
221
+ }
222
+ });
223
+ sessions = ordered;
224
+ }
225
+ if (data.backfill) {
226
+ const selection = selectBackfillSessions(sessions, changedIds ?? [], data.backfillCursor);
227
+ sessions = selection.orderedSessions;
228
+ finalizeSessionIds = selection.finalizeSessionIds;
229
+ backfillOrder = selection.orderedSessions;
230
+ backfillCursorIndex = selection.cursorIndex;
231
+ }
232
+ const scanDuration = performance.now() - startedAt;
233
+ appLogger.debug("scan.refresh_worker.scanned", {
234
+ agent: data.agentName,
235
+ source_sync: data.sourceSync ?? false,
236
+ backfill: data.backfill ?? false,
237
+ backfill_cursor: data.backfillCursor ?? void 0,
238
+ sessions: sessions.length,
239
+ changed_ids: changedIds?.length ?? 0,
240
+ source_count: sourceSyncDetails?.sourceCount,
241
+ removed_count: sourceSyncDetails?.removedCount,
242
+ duration_ms: Math.round(scanDuration)
243
+ });
244
+ const finalizeStartedAt = performance.now();
245
+ const finalizationTiming = createSessionFinalizationTiming();
246
+ const backfillPositionById = backfillOrder ? new Map(backfillOrder.map((session, index) => [session.id, index])) : void 0;
247
+ sessions = finalizeSessions(
248
+ agent,
249
+ sessions,
250
+ reportProgress,
251
+ (checkpoint) => {
252
+ let nextCheckpoint = checkpoint;
253
+ if (checkpoint.stage === "finalizing" && backfillOrder && backfillPositionById) {
254
+ let nextCursorIndex = backfillCursorIndex;
255
+ for (const { session } of checkpoint.changes) {
256
+ const index = backfillPositionById.get(session.id);
257
+ if (index != null && index > nextCursorIndex) nextCursorIndex = index;
258
+ }
259
+ if (nextCursorIndex > backfillCursorIndex) {
260
+ backfillCursorIndex = nextCursorIndex;
261
+ nextCheckpoint = {
262
+ ...checkpoint,
263
+ backfillCursor: backfillOrder[nextCursorIndex]?.id
264
+ };
265
+ }
266
+ }
267
+ parentPort?.postMessage({
268
+ type: "checkpoint",
269
+ requestId: data.requestId,
270
+ checkpoint: nextCheckpoint
271
+ });
272
+ },
273
+ finalizeSessionIds,
274
+ (batchTiming) => {
275
+ finalizationTiming.batches += 1;
276
+ addSessionTagTiming(finalizationTiming, batchTiming);
277
+ appLogger.debug("scan.refresh_worker.finalization_batch", {
278
+ agent: data.agentName,
279
+ batch: finalizationTiming.batches,
280
+ sessions: batchTiming.sessions,
281
+ cache_hits: batchTiming.cacheHits,
282
+ stale_sessions: batchTiming.staleSessions,
283
+ failed_sessions: batchTiming.failedSessions,
284
+ get_session_data_calls: batchTiming.getSessionDataCalls,
285
+ get_session_data_ms: roundMilliseconds(batchTiming.getSessionDataMs),
286
+ classify_session_tags_calls: batchTiming.classifySessionTagsCalls,
287
+ classify_session_tags_ms: roundMilliseconds(batchTiming.classifySessionTagsMs)
288
+ });
289
+ }
290
+ );
291
+ const finalizationDuration = performance.now() - finalizeStartedAt;
292
+ const otherFinalizationMs = Math.max(
293
+ 0,
294
+ finalizationDuration - finalizationTiming.getSessionDataMs - finalizationTiming.classifySessionTagsMs
295
+ );
296
+ appLogger.debug("scan.refresh_worker.finalized", {
297
+ agent: data.agentName,
298
+ backfill: data.backfill ?? false,
299
+ backfill_cursor: backfillOrder?.[backfillCursorIndex]?.id,
300
+ sessions: sessions.length,
301
+ finalized_sessions: finalizationTiming.sessions,
302
+ batches: finalizationTiming.batches,
303
+ cache_hits: finalizationTiming.cacheHits,
304
+ stale_sessions: finalizationTiming.staleSessions,
305
+ failed_sessions: finalizationTiming.failedSessions,
306
+ get_session_data_calls: finalizationTiming.getSessionDataCalls,
307
+ get_session_data_ms: roundMilliseconds(finalizationTiming.getSessionDataMs),
308
+ get_session_data_avg_ms: roundMilliseconds(
309
+ finalizationTiming.getSessionDataCalls > 0 ? finalizationTiming.getSessionDataMs / finalizationTiming.getSessionDataCalls : 0
310
+ ),
311
+ classify_session_tags_calls: finalizationTiming.classifySessionTagsCalls,
312
+ classify_session_tags_ms: roundMilliseconds(finalizationTiming.classifySessionTagsMs),
313
+ classify_session_tags_avg_ms: roundMilliseconds(
314
+ finalizationTiming.classifySessionTagsCalls > 0 ? finalizationTiming.classifySessionTagsMs / finalizationTiming.classifySessionTagsCalls : 0
315
+ ),
316
+ other_finalization_ms: roundMilliseconds(otherFinalizationMs),
317
+ duration_ms: roundMilliseconds(finalizationDuration),
318
+ total_duration_ms: Math.round(performance.now() - startedAt)
319
+ });
101
320
  const nextMeta = buildAgentCacheMeta(agent, new Set(sessions.map((session) => session.id)));
102
321
  const metaDiff = computeCacheMetaDiff(data.meta, nextMeta);
103
322
  const diff = computeSessionDiff(
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/scan-refresh-worker.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 diffSessionSources,\n ensureSessionTagsSync,\n FileSystemSessionSource,\n sessionSignature,\n type AgentScanProgress,\n type BaseAgent,\n type ScanOptions,\n type SessionCacheMeta,\n type SessionHead,\n type SessionHeadChange,\n} from \"@codesesh/core\";\n\nexport type ScanRefreshWorkerMessage =\n | {\n type: \"progress\";\n requestId: number;\n progress: AgentScanProgress;\n }\n | {\n type: \"done\";\n requestId: number;\n changes: SessionHeadChange[];\n removedSessionIds: string[];\n meta: Record<string, SessionCacheMeta>;\n removedMetaIds: string[];\n durationMs: number;\n }\n | {\n type: \"error\";\n requestId: number;\n error: string;\n durationMs: number;\n };\n\nexport interface ScanRefreshWorkerRequest {\n type: \"run\";\n requestId: number;\n agentName: string;\n previousSessions: SessionHead[];\n changedIds: string[] | null;\n sourceSync?: boolean;\n scanOptions: Pick<ScanOptions, \"from\" | \"to\" | \"fast\">;\n meta: Record<string, SessionCacheMeta>;\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\n/**\n * Source-level incremental sync. The change decision itself lives in\n * diffSessionSources so this path and FileSystemSessionSource.checkForChanges\n * cannot drift; only the re-parse and merge are local, because the worker holds\n * cached meta received over workerData rather than the agent's live metaMap.\n */\nfunction syncAgentSources(\n agent: FileSystemSessionSource,\n cachedSessions: SessionHead[],\n cachedMeta: Record<string, SessionCacheMeta>,\n windowOptions?: Pick<ScanOptions, \"from\" | \"to\">,\n): { sessions: SessionHead[]; changedIds: string[] } {\n const sessionMap = new Map(cachedSessions.map((session) => [session.id, session]));\n const sourceRefs = agent.listSessionSources(windowOptions);\n const sourceById = new Map(sourceRefs.map((source) => [source.sessionId, source]));\n const { changedIds, removedIds } = diffSessionSources(\n sourceRefs,\n cachedSessions,\n cachedMeta,\n windowOptions,\n );\n\n for (const sessionId of changedIds) {\n const source = sourceById.get(sessionId);\n if (!source) continue;\n const next = agent.scanSessionSource(source.sourcePath);\n if (next) {\n sessionMap.set(next.id, next);\n } else {\n sessionMap.delete(sessionId);\n }\n }\n\n for (const sessionId of removedIds) sessionMap.delete(sessionId);\n\n return {\n sessions: [...sessionMap.values()],\n changedIds: [...new Set([...changedIds, ...removedIds])],\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;\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(agent: BaseAgent, sessions: SessionHead[]): SessionHead[] {\n const withIdentity = attachMissingProjectIdentities(sessions);\n\n const now = Date.now();\n const settled = withIdentity.filter((session) => isSettled(session, now));\n if (settled.length === 0) return withIdentity;\n\n const taggedById = new Map(\n ensureSessionTagsSync(agent, settled).sessions.map((session) => [session.id, session]),\n );\n return withIdentity.map((session) => taggedById.get(session.id) ?? session);\n}\n\nasync function run(data: ScanRefreshWorkerRequest): Promise<void> {\n const startedAt = performance.now();\n const agent = createRegisteredAgents().find((item) => item.name === data.agentName);\n if (!agent) {\n throw new Error(`Unknown agent: ${data.agentName}`);\n }\n\n agent.setSessionMetaMap(new Map(Object.entries(data.meta)));\n\n const isAvailable = agent.isAvailable();\n let sessions: SessionHead[];\n let changedIds: string[] | undefined;\n\n if (!isAvailable) {\n sessions = [];\n } else if (data.sourceSync && agent instanceof FileSystemSessionSource) {\n const result = syncAgentSources(agent, data.previousSessions, data.meta, data.scanOptions);\n sessions = result.sessions;\n changedIds = result.changedIds;\n } else if (data.changedIds) {\n sessions = await Promise.resolve(agent.incrementalScan(data.previousSessions, data.changedIds));\n } else {\n sessions = await Promise.resolve(\n agent.scan({\n ...data.scanOptions,\n onProgress: (progress) => {\n parentPort?.postMessage({\n type: \"progress\",\n requestId: data.requestId,\n progress,\n } satisfies ScanRefreshWorkerMessage);\n },\n }),\n );\n }\n\n sessions = finalizeSessions(agent, sessions);\n const nextMeta = buildAgentCacheMeta(agent, new Set(sessions.map((session) => session.id)));\n const metaDiff = computeCacheMetaDiff(data.meta, nextMeta);\n const diff = computeSessionDiff(\n data.previousSessions,\n sessions,\n [...(changedIds ?? []), ...Object.keys(metaDiff.changes), ...metaDiff.removedIds],\n sessionSignature,\n );\n\n parentPort?.postMessage({\n type: \"done\",\n requestId: data.requestId,\n changes: diff.changes,\n removedSessionIds: diff.removedSessionIds,\n meta: metaDiff.changes,\n removedMetaIds: metaDiff.removedIds,\n durationMs: performance.now() - startedAt,\n } satisfies ScanRefreshWorkerMessage);\n}\n\nasync function handleRequest(data: ScanRefreshWorkerRequest): Promise<void> {\n const startedAt = performance.now();\n try {\n await run(data);\n } catch (error) {\n parentPort?.postMessage({\n type: \"error\",\n requestId: data.requestId,\n error: error instanceof Error ? error.message : String(error),\n durationMs: performance.now() - startedAt,\n } satisfies ScanRefreshWorkerMessage);\n }\n}\n\nlet requestTail = Promise.resolve();\n\nfunction enqueueRequest(data: ScanRefreshWorkerRequest): void {\n requestTail = requestTail.then(() => handleRequest(data));\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 Array.isArray(initialRequest.previousSessions)\n) {\n enqueueRequest(initialRequest as ScanRefreshWorkerRequest);\n}\n\nparentPort?.on(\"message\", (message: ScanRefreshWorkerRequest) => {\n if (message.type === \"run\") enqueueRequest(message);\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/scan-refresh-worker.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 diffSessionSources,\n ensureSessionTagsSync,\n FileSystemSessionSource,\n sessionSignature,\n sortSessions,\n type AgentScanProgress,\n type BaseAgent,\n type ScanOptions,\n type SessionCacheMeta,\n type SessionHead,\n type SessionHeadChange,\n type SessionTagTiming,\n} from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\n\nexport type ScanRefreshWorkerMessage =\n | {\n type: \"progress\";\n requestId: number;\n progress: AgentScanProgress;\n }\n | {\n type: \"checkpoint\";\n requestId: number;\n checkpoint: ScanRefreshWorkerCheckpoint;\n }\n | {\n type: \"done\";\n requestId: number;\n changes: SessionHeadChange[];\n removedSessionIds: string[];\n meta: Record<string, SessionCacheMeta>;\n removedMetaIds: string[];\n durationMs: number;\n }\n | {\n type: \"error\";\n requestId: 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 }\n | {\n stage: \"finalizing\";\n changes: SessionHeadChange[];\n meta: Record<string, SessionCacheMeta>;\n backfillCursor?: string;\n };\n\nexport interface ScanRefreshWorkerRequest {\n type: \"run\";\n requestId: number;\n agentName: string;\n previousSessions: SessionHead[];\n changedIds: string[] | null;\n sourceSync?: boolean;\n backfill?: boolean;\n backfillCursor?: string | null;\n checkpoint?: boolean;\n scanOptions: Pick<ScanOptions, \"from\" | \"to\" | \"fast\">;\n meta: Record<string, SessionCacheMeta>;\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) || session.smart_tags_source_updated_at !== sourceUpdatedAt\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 * Source-level incremental sync. The change decision itself lives in\n * diffSessionSources so this path and FileSystemSessionSource.checkForChanges\n * cannot drift; only the expansion, re-parse and merge are local, because the\n * worker holds cached meta received over workerData rather than the agent's\n * live metaMap.\n */\nfunction syncAgentSources(\n agent: FileSystemSessionSource,\n cachedSessions: SessionHead[],\n cachedMeta: Record<string, SessionCacheMeta>,\n windowOptions?: Pick<ScanOptions, \"from\" | \"to\">,\n onProgress?: (progress: AgentScanProgress) => void,\n): {\n sessions: SessionHead[];\n changedIds: string[];\n finalizeSessionIds: string[];\n sourceCount: number;\n removedCount: number;\n} {\n const sessionMap = new Map(cachedSessions.map((session) => [session.id, session]));\n const sourceRefs = agent.listSessionSources(windowOptions);\n const sourceById = new Map(sourceRefs.map((source) => [source.sessionId, source]));\n const { changedIds, removedIds } = diffSessionSources(\n sourceRefs,\n cachedSessions,\n cachedMeta,\n windowOptions,\n );\n // Expansion pulls in sessions whose derived data depends on the changed ones\n // (e.g. parents of changed subagent files), so a targeted re-parse stays\n // correct without rescanning the whole directory.\n const rescanIds = agent.expandChangedSessionIds?.(\n [...new Set([...changedIds, ...removedIds])],\n sourceRefs,\n ) ?? [...new Set([...changedIds, ...removedIds])];\n const isWindowed = windowOptions?.from != null || windowOptions?.to != null;\n const finalizeSessionIds = isWindowed\n ? [...rescanIds]\n : sourceRefs.map((source) => source.sessionId);\n\n rescanIds.forEach((sessionId, index) => {\n const source = sourceById.get(sessionId);\n if (!source) return;\n const next = agent.scanSessionSource(source.sourcePath);\n if (next) {\n sessionMap.set(next.id, next);\n } else {\n sessionMap.delete(sessionId);\n }\n onProgress?.({ total: rescanIds.length, processed: index + 1, sessions: sessionMap.size });\n });\n\n for (const sessionId of removedIds) sessionMap.delete(sessionId);\n\n return {\n sessions: [...sessionMap.values()],\n changedIds: rescanIds,\n finalizeSessionIds,\n sourceCount: sourceRefs.length,\n removedCount: removedIds.length,\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;\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\nasync function run(data: ScanRefreshWorkerRequest): Promise<void> {\n const startedAt = performance.now();\n const agent = createRegisteredAgents().find((item) => item.name === data.agentName);\n if (!agent) {\n throw new Error(`Unknown agent: ${data.agentName}`);\n }\n\n appLogger.debug(\"scan.refresh_worker.started\", {\n agent: data.agentName,\n source_sync: data.sourceSync ?? false,\n backfill: data.backfill ?? false,\n backfill_cursor: data.backfillCursor ?? undefined,\n changed_ids: data.changedIds?.length ?? 0,\n previous_sessions: data.previousSessions.length,\n });\n\n const reportProgress = (progress: AgentScanProgress): void => {\n parentPort?.postMessage({\n type: \"progress\",\n requestId: data.requestId,\n progress,\n } satisfies ScanRefreshWorkerMessage);\n };\n\n agent.setSessionMetaMap(new Map(Object.entries(data.meta)));\n\n const isAvailable = agent.isAvailable();\n let sessions: SessionHead[];\n let changedIds: string[] | undefined;\n let finalizeSessionIds: ReadonlySet<string> | undefined;\n let backfillOrder: SessionHead[] | undefined;\n let backfillCursorIndex = -1;\n let sourceSyncDetails:\n | {\n sourceCount: number;\n removedCount: number;\n }\n | undefined;\n\n if (!isAvailable) {\n sessions = [];\n } else if (data.sourceSync && agent instanceof FileSystemSessionSource) {\n const result = syncAgentSources(\n agent,\n data.previousSessions,\n data.meta,\n data.scanOptions,\n reportProgress,\n );\n sessions = result.sessions;\n changedIds = result.changedIds;\n finalizeSessionIds = new Set(result.finalizeSessionIds);\n sourceSyncDetails = result;\n } else if (data.changedIds) {\n sessions = await Promise.resolve(agent.incrementalScan(data.previousSessions, data.changedIds));\n } else {\n sessions = await Promise.resolve(\n agent.scan({\n ...data.scanOptions,\n onProgress: reportProgress,\n }),\n );\n }\n\n sessions = attachMissingProjectIdentities(sessions);\n if (data.checkpoint) {\n const ordered = sortSessions(sessions);\n parentPort?.postMessage({\n type: \"checkpoint\",\n requestId: data.requestId,\n checkpoint: {\n stage: \"scanned\",\n sessions: ordered,\n meta: buildAgentCacheMeta(agent, new Set(ordered.map((session) => session.id))),\n },\n } satisfies ScanRefreshWorkerMessage);\n sessions = ordered;\n }\n\n if (data.backfill) {\n const selection = selectBackfillSessions(sessions, changedIds ?? [], data.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 source_sync: data.sourceSync ?? false,\n backfill: data.backfill ?? false,\n backfill_cursor: data.backfillCursor ?? undefined,\n sessions: sessions.length,\n changed_ids: changedIds?.length ?? 0,\n source_count: sourceSyncDetails?.sourceCount,\n removed_count: sourceSyncDetails?.removedCount,\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 (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 checkpoint: nextCheckpoint,\n } satisfies ScanRefreshWorkerMessage);\n },\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 backfill: data.backfill ?? false,\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(data.meta, nextMeta);\n const diff = computeSessionDiff(\n data.previousSessions,\n sessions,\n [...(changedIds ?? []), ...Object.keys(metaDiff.changes), ...metaDiff.removedIds],\n sessionSignature,\n );\n\n parentPort?.postMessage({\n type: \"done\",\n requestId: data.requestId,\n changes: diff.changes,\n removedSessionIds: diff.removedSessionIds,\n meta: metaDiff.changes,\n removedMetaIds: metaDiff.removedIds,\n durationMs: performance.now() - startedAt,\n } satisfies ScanRefreshWorkerMessage);\n}\n\nasync function handleRequest(data: ScanRefreshWorkerRequest): Promise<void> {\n const startedAt = performance.now();\n try {\n await run(data);\n } catch (error) {\n parentPort?.postMessage({\n type: \"error\",\n requestId: data.requestId,\n error: error instanceof Error ? error.message : String(error),\n durationMs: performance.now() - startedAt,\n } satisfies ScanRefreshWorkerMessage);\n }\n}\n\nlet requestTail = Promise.resolve();\n\nfunction enqueueRequest(data: ScanRefreshWorkerRequest): void {\n requestTail = requestTail.then(() => handleRequest(data));\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 Array.isArray(initialRequest.previousSessions)\n) {\n enqueueRequest(initialRequest as ScanRefreshWorkerRequest);\n}\n\nparentPort?.on(\"message\", (message: ScanRefreshWorkerRequest) => {\n if (message.type === \"run\") enqueueRequest(message);\n});\n"],"mappings":"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","names":["now"]}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  appLogger
4
- } from "./chunk-A4U2SMJJ.js";
4
+ } from "./chunk-KD3DGWZY.js";
5
5
  import {
6
6
  createRegisteredAgents,
7
7
  markAgentCacheInitialized,
@@ -9,7 +9,7 @@ import {
9
9
  saveCachedSessions,
10
10
  syncSessionSearchIndex,
11
11
  syncSessionSearchIndexChanges
12
- } from "./chunk-7APNDHQ6.js";
12
+ } from "./chunk-G2BTNW3C.js";
13
13
 
14
14
  // src/search-index-worker.ts
15
15
  import { parentPort, workerData } from "worker_threads";
@@ -25,55 +25,89 @@ var jobs = data.jobs ?? data.agentNames.map(
25
25
  meta: data.metaByAgent[agentName] ?? {}
26
26
  })
27
27
  );
28
- for (const job of jobs) {
29
- const agent = agents.find((item) => item.name === job.agentName);
30
- if (!agent) continue;
31
- if (agent.setSessionMetaMap) {
32
- agent.setSessionMetaMap(new Map(Object.entries(job.meta)));
33
- }
34
- let result;
28
+ function jobSessionCount(job) {
29
+ return job.kind === "full" ? job.sessions.length : job.changes.length;
30
+ }
31
+ function reportPersistFailure(job, stage) {
32
+ appLogger.error("search_index.persist_failed", {
33
+ context: job.context,
34
+ stage,
35
+ agent: job.agentName,
36
+ sessions: jobSessionCount(job)
37
+ });
38
+ parentPort?.postMessage({
39
+ type: "persist-failed",
40
+ context: job.context,
41
+ stage,
42
+ agentName: job.agentName,
43
+ sessions: jobSessionCount(job)
44
+ });
45
+ }
46
+ function runJob(job, agent) {
35
47
  if (job.kind === "changes") {
36
- saveCachedSessionChanges(job.agentName, job.changes, job.removedSessionIds, job.meta);
37
- result = syncSessionSearchIndexChanges(
48
+ if (!saveCachedSessionChanges(job.agentName, job.changes, job.removedSessionIds, job.meta)) {
49
+ return "cache";
50
+ }
51
+ const result2 = syncSessionSearchIndexChanges(
38
52
  job.agentName,
39
53
  job.changes,
40
54
  job.removedSessionIds,
41
55
  (sessionId) => agent.getSessionData(sessionId),
42
56
  job.searchIndexOptions
43
57
  );
44
- } else {
45
- if (job.saveCache) {
46
- saveCachedSessions(job.agentName, job.sessions, job.meta);
47
- }
48
- result = syncSessionSearchIndex(
49
- job.agentName,
50
- job.sessions,
51
- (sessionId) => agent.getSessionData(sessionId),
52
- job.searchIndexOptions
53
- );
54
- if (job.saveCache && result) {
55
- markAgentCacheInitialized(job.agentName);
56
- if (result.skipped > 0) {
57
- appLogger.warn("search_index.sync_incomplete", {
58
- agent: job.agentName,
59
- skipped: result.skipped
60
- });
61
- }
58
+ if (!result2) return "search_index";
59
+ postSyncResult(job.context, result2);
60
+ return null;
61
+ }
62
+ if (job.saveCache && !saveCachedSessions(job.agentName, job.sessions, job.meta)) {
63
+ return "cache";
64
+ }
65
+ const result = syncSessionSearchIndex(
66
+ job.agentName,
67
+ job.sessions,
68
+ (sessionId) => agent.getSessionData(sessionId),
69
+ job.searchIndexOptions
70
+ );
71
+ if (!result) return "search_index";
72
+ if (job.saveCache) {
73
+ markAgentCacheInitialized(job.agentName);
74
+ if (result.skipped > 0) {
75
+ appLogger.warn("search_index.sync_incomplete", {
76
+ agent: job.agentName,
77
+ skipped: result.skipped
78
+ });
62
79
  }
63
80
  }
81
+ postSyncResult(job.context, result);
82
+ return null;
83
+ }
84
+ function postSyncResult(context, result) {
64
85
  parentPort?.postMessage({
65
86
  type: "sync-result",
66
- context: job.context,
87
+ context,
67
88
  result
68
89
  });
69
90
  }
70
- parentPort?.postMessage({
71
- type: "done",
72
- context: data.context,
73
- durationMs: performance.now() - startedAt,
74
- sessions: jobs.reduce(
75
- (total, job) => total + (job.kind === "full" ? job.sessions.length : job.changes.length),
76
- 0
77
- )
78
- });
91
+ var persistFailed = false;
92
+ for (const job of jobs) {
93
+ const agent = agents.find((item) => item.name === job.agentName);
94
+ if (!agent) continue;
95
+ if (agent.setSessionMetaMap) {
96
+ agent.setSessionMetaMap(new Map(Object.entries(job.meta)));
97
+ }
98
+ const failedStage = runJob(job, agent);
99
+ if (failedStage) {
100
+ reportPersistFailure(job, failedStage);
101
+ persistFailed = true;
102
+ break;
103
+ }
104
+ }
105
+ if (!persistFailed) {
106
+ parentPort?.postMessage({
107
+ type: "done",
108
+ context: data.context,
109
+ durationMs: performance.now() - startedAt,
110
+ sessions: jobs.reduce((total, job) => total + jobSessionCount(job), 0)
111
+ });
112
+ }
79
113
  //# sourceMappingURL=search-index-worker.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/search-index-worker.ts"],"sourcesContent":["import \"./diagnostics-bridge.js\";\nimport { parentPort, workerData } from \"node:worker_threads\";\nimport {\n createRegisteredAgents,\n markAgentCacheInitialized,\n saveCachedSessionChanges,\n saveCachedSessions,\n syncSessionSearchIndex,\n syncSessionSearchIndexChanges,\n type SearchIndexSyncResult,\n type SearchIndexSyncOptions,\n type SessionCacheMeta,\n type SessionHeadChange,\n type SessionHead,\n} from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\n\nexport type SearchIndexWorkerMessage =\n | {\n type: \"sync-result\";\n context: string;\n result: SearchIndexSyncResult | null;\n }\n | {\n type: \"done\";\n context: string;\n durationMs: number;\n sessions: number;\n };\n\nexport type SearchIndexWorkerJob =\n | {\n kind: \"full\";\n context: string;\n agentName: string;\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n saveCache?: boolean;\n searchIndexOptions?: SearchIndexSyncOptions;\n }\n | {\n kind: \"changes\";\n context: string;\n agentName: string;\n changes: SessionHeadChange[];\n removedSessionIds: string[];\n meta: Record<string, SessionCacheMeta>;\n searchIndexOptions?: SearchIndexSyncOptions;\n };\n\ninterface SearchIndexWorkerData {\n jobs?: SearchIndexWorkerJob[];\n context: string;\n agentNames: string[];\n sessionsByAgent: Record<string, SessionHead[]>;\n metaByAgent: Record<string, Record<string, SessionCacheMeta>>;\n}\n\nconst data = workerData as SearchIndexWorkerData;\nconst startedAt = performance.now();\nconst agents = createRegisteredAgents();\nconst jobs =\n data.jobs ??\n data.agentNames.map(\n (agentName): SearchIndexWorkerJob => ({\n kind: \"full\",\n context: data.context,\n agentName,\n sessions: data.sessionsByAgent[agentName] ?? [],\n meta: data.metaByAgent[agentName] ?? {},\n }),\n );\n\nfor (const job of jobs) {\n const agent = agents.find((item) => item.name === job.agentName);\n if (!agent) continue;\n\n if (agent.setSessionMetaMap) {\n agent.setSessionMetaMap(new Map(Object.entries(job.meta)));\n }\n\n let result: SearchIndexSyncResult | null;\n if (job.kind === \"changes\") {\n saveCachedSessionChanges(job.agentName, job.changes, job.removedSessionIds, job.meta);\n result = syncSessionSearchIndexChanges(\n job.agentName,\n job.changes,\n job.removedSessionIds,\n (sessionId) => agent.getSessionData(sessionId),\n job.searchIndexOptions,\n );\n } else {\n if (job.saveCache) {\n saveCachedSessions(job.agentName, job.sessions, job.meta);\n }\n result = syncSessionSearchIndex(\n job.agentName,\n job.sessions,\n (sessionId) => agent.getSessionData(sessionId),\n job.searchIndexOptions,\n );\n // Head cache init is decoupled from search-index completeness (CS-73): a\n // session that fails to load must not permanently block markAgentCacheInitialized,\n // or every future refresh would fall back to a full initializeAgent scan.\n // The skip is still surfaced as a warning so it stays visible.\n if (job.saveCache && result) {\n markAgentCacheInitialized(job.agentName);\n if (result.skipped > 0) {\n appLogger.warn(\"search_index.sync_incomplete\", {\n agent: job.agentName,\n skipped: result.skipped,\n });\n }\n }\n }\n parentPort?.postMessage({\n type: \"sync-result\",\n context: job.context,\n result,\n } satisfies SearchIndexWorkerMessage);\n}\n\nparentPort?.postMessage({\n type: \"done\",\n context: data.context,\n durationMs: performance.now() - startedAt,\n sessions: jobs.reduce(\n (total, job) => total + (job.kind === \"full\" ? job.sessions.length : job.changes.length),\n 0,\n ),\n} satisfies SearchIndexWorkerMessage);\n"],"mappings":";;;;;;;;;;;;;;AACA,SAAS,YAAY,kBAAkB;AAyDvC,IAAM,OAAO;AACb,IAAM,YAAY,YAAY,IAAI;AAClC,IAAM,SAAS,uBAAuB;AACtC,IAAM,OACJ,KAAK,QACL,KAAK,WAAW;AAAA,EACd,CAAC,eAAqC;AAAA,IACpC,MAAM;AAAA,IACN,SAAS,KAAK;AAAA,IACd;AAAA,IACA,UAAU,KAAK,gBAAgB,SAAS,KAAK,CAAC;AAAA,IAC9C,MAAM,KAAK,YAAY,SAAS,KAAK,CAAC;AAAA,EACxC;AACF;AAEF,WAAW,OAAO,MAAM;AACtB,QAAM,QAAQ,OAAO,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,SAAS;AAC/D,MAAI,CAAC,MAAO;AAEZ,MAAI,MAAM,mBAAmB;AAC3B,UAAM,kBAAkB,IAAI,IAAI,OAAO,QAAQ,IAAI,IAAI,CAAC,CAAC;AAAA,EAC3D;AAEA,MAAI;AACJ,MAAI,IAAI,SAAS,WAAW;AAC1B,6BAAyB,IAAI,WAAW,IAAI,SAAS,IAAI,mBAAmB,IAAI,IAAI;AACpF,aAAS;AAAA,MACP,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,CAAC,cAAc,MAAM,eAAe,SAAS;AAAA,MAC7C,IAAI;AAAA,IACN;AAAA,EACF,OAAO;AACL,QAAI,IAAI,WAAW;AACjB,yBAAmB,IAAI,WAAW,IAAI,UAAU,IAAI,IAAI;AAAA,IAC1D;AACA,aAAS;AAAA,MACP,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,CAAC,cAAc,MAAM,eAAe,SAAS;AAAA,MAC7C,IAAI;AAAA,IACN;AAKA,QAAI,IAAI,aAAa,QAAQ;AAC3B,gCAA0B,IAAI,SAAS;AACvC,UAAI,OAAO,UAAU,GAAG;AACtB,kBAAU,KAAK,gCAAgC;AAAA,UAC7C,OAAO,IAAI;AAAA,UACX,SAAS,OAAO;AAAA,QAClB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACA,cAAY,YAAY;AAAA,IACtB,MAAM;AAAA,IACN,SAAS,IAAI;AAAA,IACb;AAAA,EACF,CAAoC;AACtC;AAEA,YAAY,YAAY;AAAA,EACtB,MAAM;AAAA,EACN,SAAS,KAAK;AAAA,EACd,YAAY,YAAY,IAAI,IAAI;AAAA,EAChC,UAAU,KAAK;AAAA,IACb,CAAC,OAAO,QAAQ,SAAS,IAAI,SAAS,SAAS,IAAI,SAAS,SAAS,IAAI,QAAQ;AAAA,IACjF;AAAA,EACF;AACF,CAAoC;","names":[]}
1
+ {"version":3,"sources":["../src/search-index-worker.ts"],"sourcesContent":["import \"./diagnostics-bridge.js\";\nimport { parentPort, workerData } from \"node:worker_threads\";\nimport {\n createRegisteredAgents,\n markAgentCacheInitialized,\n saveCachedSessionChanges,\n saveCachedSessions,\n syncSessionSearchIndex,\n syncSessionSearchIndexChanges,\n type SearchIndexSyncResult,\n type SearchIndexSyncOptions,\n type SessionCacheMeta,\n type SessionHeadChange,\n type SessionHead,\n} from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\n\nexport type SearchIndexPersistStage = \"cache\" | \"search_index\";\n\nexport type SearchIndexWorkerMessage =\n | {\n type: \"sync-result\";\n context: string;\n result: SearchIndexSyncResult | null;\n }\n | {\n type: \"persist-failed\";\n context: string;\n stage: SearchIndexPersistStage;\n agentName: string;\n sessions: number;\n }\n | {\n type: \"done\";\n context: string;\n durationMs: number;\n sessions: number;\n };\n\nexport type SearchIndexWorkerJob =\n | {\n kind: \"full\";\n context: string;\n agentName: string;\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n saveCache?: boolean;\n searchIndexOptions?: SearchIndexSyncOptions;\n }\n | {\n kind: \"changes\";\n context: string;\n agentName: string;\n changes: SessionHeadChange[];\n removedSessionIds: string[];\n meta: Record<string, SessionCacheMeta>;\n searchIndexOptions?: SearchIndexSyncOptions;\n };\n\ninterface SearchIndexWorkerData {\n jobs?: SearchIndexWorkerJob[];\n context: string;\n agentNames: string[];\n sessionsByAgent: Record<string, SessionHead[]>;\n metaByAgent: Record<string, Record<string, SessionCacheMeta>>;\n}\n\ntype WorkerAgent = ReturnType<typeof createRegisteredAgents>[number];\n\nconst data = workerData as SearchIndexWorkerData;\nconst startedAt = performance.now();\nconst agents = createRegisteredAgents();\nconst jobs =\n data.jobs ??\n data.agentNames.map(\n (agentName): SearchIndexWorkerJob => ({\n kind: \"full\",\n context: data.context,\n agentName,\n sessions: data.sessionsByAgent[agentName] ?? [],\n meta: data.metaByAgent[agentName] ?? {},\n }),\n );\n\nfunction jobSessionCount(job: SearchIndexWorkerJob): number {\n return job.kind === \"full\" ? job.sessions.length : job.changes.length;\n}\n\n/**\n * Reports a persistence failure so the batch is rejected instead of settling as\n * `done`; the caller keeps its previously published snapshot and can retry.\n */\nfunction reportPersistFailure(job: SearchIndexWorkerJob, stage: SearchIndexPersistStage): void {\n appLogger.error(\"search_index.persist_failed\", {\n context: job.context,\n stage,\n agent: job.agentName,\n sessions: jobSessionCount(job),\n });\n parentPort?.postMessage({\n type: \"persist-failed\",\n context: job.context,\n stage,\n agentName: job.agentName,\n sessions: jobSessionCount(job),\n } satisfies SearchIndexWorkerMessage);\n}\n\nfunction runJob(job: SearchIndexWorkerJob, agent: WorkerAgent): SearchIndexPersistStage | null {\n if (job.kind === \"changes\") {\n if (!saveCachedSessionChanges(job.agentName, job.changes, job.removedSessionIds, job.meta)) {\n return \"cache\";\n }\n const result = syncSessionSearchIndexChanges(\n job.agentName,\n job.changes,\n job.removedSessionIds,\n (sessionId) => agent.getSessionData(sessionId),\n job.searchIndexOptions,\n );\n if (!result) return \"search_index\";\n postSyncResult(job.context, result);\n return null;\n }\n\n if (job.saveCache && !saveCachedSessions(job.agentName, job.sessions, job.meta)) {\n return \"cache\";\n }\n const result = syncSessionSearchIndex(\n job.agentName,\n job.sessions,\n (sessionId) => agent.getSessionData(sessionId),\n job.searchIndexOptions,\n );\n if (!result) return \"search_index\";\n // Head cache init is decoupled from search-index completeness (CS-73): a\n // session that fails to load must not permanently block markAgentCacheInitialized,\n // or every future refresh would fall back to a full initializeAgent scan.\n // The skip is still surfaced as a warning so it stays visible.\n if (job.saveCache) {\n markAgentCacheInitialized(job.agentName);\n if (result.skipped > 0) {\n appLogger.warn(\"search_index.sync_incomplete\", {\n agent: job.agentName,\n skipped: result.skipped,\n });\n }\n }\n postSyncResult(job.context, result);\n return null;\n}\n\nfunction postSyncResult(context: string, result: SearchIndexSyncResult): void {\n parentPort?.postMessage({\n type: \"sync-result\",\n context,\n result,\n } satisfies SearchIndexWorkerMessage);\n}\n\nlet persistFailed = false;\nfor (const job of jobs) {\n const agent = agents.find((item) => item.name === job.agentName);\n if (!agent) continue;\n\n if (agent.setSessionMetaMap) {\n agent.setSessionMetaMap(new Map(Object.entries(job.meta)));\n }\n\n const failedStage = runJob(job, agent);\n if (failedStage) {\n reportPersistFailure(job, failedStage);\n persistFailed = true;\n break;\n }\n}\n\nif (!persistFailed) {\n parentPort?.postMessage({\n type: \"done\",\n context: data.context,\n durationMs: performance.now() - startedAt,\n sessions: jobs.reduce((total, job) => total + jobSessionCount(job), 0),\n } satisfies SearchIndexWorkerMessage);\n}\n"],"mappings":"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","names":["result"]}
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-A4U2SMJJ.js";
2
+ import "./chunk-KD3DGWZY.js";
3
3
  import {
4
4
  classifySessionTags,
5
5
  createRegisteredAgents,
6
6
  getSmartTagSourceTimestamp
7
- } from "./chunk-7APNDHQ6.js";
7
+ } from "./chunk-G2BTNW3C.js";
8
8
 
9
9
  // src/smart-tag-worker.ts
10
10
  import { parentPort, workerData } from "worker_threads";