codesesh 0.9.1 → 0.10.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.
- package/dist/{chunk-5UOLRSFH.js → chunk-ZQMIB7QO.js} +2137 -2228
- package/dist/chunk-ZQMIB7QO.js.map +1 -0
- package/dist/{dist-VEIV33FR.js → dist-GZSUB4NY.js} +30 -2
- package/dist/index.js +467 -636
- package/dist/index.js.map +1 -1
- package/dist/scan-refresh-worker.js +7 -13
- package/dist/scan-refresh-worker.js.map +1 -1
- package/dist/search-index-worker.js +1 -1
- package/dist/smart-tag-worker.js +1 -1
- package/dist/web/assets/index-CxJTOv8L.js +111 -0
- package/dist/web/assets/vendor-CQhWyNUf.js +40 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/chunk-5UOLRSFH.js.map +0 -1
- package/dist/web/assets/index-CT4gLIAq.js +0 -111
- package/dist/web/assets/vendor-Da5am_Td.js +0 -40
- /package/dist/{dist-VEIV33FR.js.map → dist-GZSUB4NY.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
BookmarkStorageUnavailableError,
|
|
4
|
+
FileSystemSessionSource,
|
|
5
|
+
attachMissingProjectIdentities,
|
|
6
|
+
buildAgentCacheMeta,
|
|
7
|
+
buildDashboard,
|
|
4
8
|
classifySessionTags,
|
|
5
9
|
computeIdentity,
|
|
10
|
+
computeSessionDiff,
|
|
6
11
|
createProjectScopeMatcher,
|
|
7
12
|
createRegisteredAgents,
|
|
8
13
|
deleteBookmark,
|
|
@@ -10,7 +15,10 @@ import {
|
|
|
10
15
|
filterSessions,
|
|
11
16
|
getAgentInfoMap,
|
|
12
17
|
getCursorDataPath,
|
|
18
|
+
getSessionActivityTime,
|
|
19
|
+
getSessionAgentName,
|
|
13
20
|
getSmartTagSourceTimestamp,
|
|
21
|
+
getTotalTokens,
|
|
14
22
|
importBookmarks,
|
|
15
23
|
isAgentCacheInitialized,
|
|
16
24
|
listBookmarks,
|
|
@@ -28,8 +36,11 @@ import {
|
|
|
28
36
|
scanSessions,
|
|
29
37
|
searchFileActivitySessions,
|
|
30
38
|
searchSessions,
|
|
39
|
+
sessionSignature,
|
|
40
|
+
sortSessions,
|
|
41
|
+
startOfLocalDay,
|
|
31
42
|
upsertBookmark
|
|
32
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-ZQMIB7QO.js";
|
|
33
44
|
|
|
34
45
|
// src/index.ts
|
|
35
46
|
import { defineCommand, runMain } from "citty";
|
|
@@ -195,7 +206,6 @@ function logSearchIndexSync(context, result, data = {}) {
|
|
|
195
206
|
}
|
|
196
207
|
|
|
197
208
|
// src/api/handlers.ts
|
|
198
|
-
var DASHBOARD_RECENT_LIMIT = 10;
|
|
199
209
|
function isRecord(value) {
|
|
200
210
|
return typeof value === "object" && value !== null;
|
|
201
211
|
}
|
|
@@ -219,15 +229,6 @@ function parseBookmarkPayload(value) {
|
|
|
219
229
|
stats: value.stats
|
|
220
230
|
};
|
|
221
231
|
}
|
|
222
|
-
function getTotalTokens(stats) {
|
|
223
|
-
return stats.total_tokens ?? stats.total_input_tokens + stats.total_output_tokens;
|
|
224
|
-
}
|
|
225
|
-
function getSessionAgentName(session) {
|
|
226
|
-
return session.slug.split("/")[0]?.toLowerCase() || "unknown";
|
|
227
|
-
}
|
|
228
|
-
function getSessionActivityTime(session) {
|
|
229
|
-
return session.time_updated ?? session.time_created;
|
|
230
|
-
}
|
|
231
232
|
function parseDateParam(value, fallback) {
|
|
232
233
|
if (value == null) return fallback;
|
|
233
234
|
const ts = new Date(value).getTime();
|
|
@@ -682,18 +683,6 @@ function handleDeleteBookmark(c) {
|
|
|
682
683
|
throw error;
|
|
683
684
|
}
|
|
684
685
|
}
|
|
685
|
-
function toLocalDateKey(ts) {
|
|
686
|
-
const d = new Date(ts);
|
|
687
|
-
const year = d.getFullYear();
|
|
688
|
-
const month = `${d.getMonth() + 1}`.padStart(2, "0");
|
|
689
|
-
const day = `${d.getDate()}`.padStart(2, "0");
|
|
690
|
-
return `${year}-${month}-${day}`;
|
|
691
|
-
}
|
|
692
|
-
function startOfLocalDay(ts) {
|
|
693
|
-
const d = new Date(ts);
|
|
694
|
-
d.setHours(0, 0, 0, 0);
|
|
695
|
-
return d.getTime();
|
|
696
|
-
}
|
|
697
686
|
function resolveDashboardWindow(defaults, queryDays, queryFrom, queryTo) {
|
|
698
687
|
const now = Date.now();
|
|
699
688
|
const toTs = parseDateParam(queryTo, defaults.to) ?? now;
|
|
@@ -732,138 +721,17 @@ function handleGetDashboard(c, scanSource, defaults = {}) {
|
|
|
732
721
|
projectKind: optionalQueryValue(c.req.query("projectKind")),
|
|
733
722
|
projectKey: optionalQueryValue(c.req.query("projectKey"))
|
|
734
723
|
};
|
|
735
|
-
const agentMetrics = /* @__PURE__ */ new Map();
|
|
736
|
-
const agentMetricKeyByName = /* @__PURE__ */ new Map();
|
|
737
|
-
for (const name of Object.keys(scanResult.byAgent)) {
|
|
738
|
-
if (scope.agent && name.toLowerCase() !== scope.agent) continue;
|
|
739
|
-
agentMetrics.set(name, { sessions: 0, messages: 0, tokens: 0 });
|
|
740
|
-
agentMetricKeyByName.set(name.toLowerCase(), name);
|
|
741
|
-
}
|
|
742
724
|
const agentInfo = getAgentInfoMap({});
|
|
743
725
|
const agentInfoMap = new Map(agentInfo.map((a) => [a.name, a]));
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
const recentCandidates = [];
|
|
751
|
-
const modelAgg = /* @__PURE__ */ new Map();
|
|
752
|
-
const dailyMap = /* @__PURE__ */ new Map();
|
|
753
|
-
const dailyTokenMap = /* @__PURE__ */ new Map();
|
|
754
|
-
if (from != null) {
|
|
755
|
-
const bucketStart = startOfLocalDay(from);
|
|
756
|
-
const bucketDays = Math.floor((startOfLocalDay(to) - bucketStart) / 864e5) + 1;
|
|
757
|
-
for (let i = 0; i < bucketDays; i += 1) {
|
|
758
|
-
const ts = bucketStart + i * 864e5;
|
|
759
|
-
const key = toLocalDateKey(ts);
|
|
760
|
-
dailyMap.set(key, { date: key, sessions: 0, messages: 0 });
|
|
761
|
-
dailyTokenMap.set(key, { date: key, input: 0, output: 0, cache_read: 0, cache_create: 0 });
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
for (const session of scanResult.sessions) {
|
|
765
|
-
const agentName = getSessionAgentName(session);
|
|
766
|
-
if (scope.agent && agentName !== scope.agent) continue;
|
|
767
|
-
if (scope.projectKey) {
|
|
768
|
-
const identity = session.project_identity;
|
|
769
|
-
if (!identity || identity.key !== scope.projectKey) continue;
|
|
770
|
-
if (scope.projectKind && identity.kind !== scope.projectKind) continue;
|
|
771
|
-
}
|
|
772
|
-
const activity = getSessionActivityTime(session);
|
|
773
|
-
if (from != null && activity < from) continue;
|
|
774
|
-
if (activity > to) continue;
|
|
775
|
-
const messageCount = session.stats.message_count;
|
|
776
|
-
const sessionTokens = getTotalTokens(session.stats);
|
|
777
|
-
totalSessions += 1;
|
|
778
|
-
totalMessages += messageCount;
|
|
779
|
-
totalTokens += sessionTokens;
|
|
780
|
-
totalCost += session.stats.total_cost ?? 0;
|
|
781
|
-
if (session.stats.cost_source === "estimated") hasEstimatedCost = true;
|
|
782
|
-
if (activity > latestActivity) latestActivity = activity;
|
|
783
|
-
const metricKey = agentMetricKeyByName.get(agentName);
|
|
784
|
-
if (metricKey) {
|
|
785
|
-
const metric = agentMetrics.get(metricKey);
|
|
786
|
-
metric.sessions += 1;
|
|
787
|
-
metric.messages += messageCount;
|
|
788
|
-
metric.tokens += sessionTokens;
|
|
789
|
-
}
|
|
790
|
-
const key = toLocalDateKey(activity);
|
|
791
|
-
let bucket = dailyMap.get(key);
|
|
792
|
-
if (!bucket) {
|
|
793
|
-
bucket = { date: key, sessions: 0, messages: 0 };
|
|
794
|
-
dailyMap.set(key, bucket);
|
|
795
|
-
}
|
|
796
|
-
bucket.sessions += 1;
|
|
797
|
-
bucket.messages += messageCount;
|
|
798
|
-
let tokenBucket = dailyTokenMap.get(key);
|
|
799
|
-
if (!tokenBucket) {
|
|
800
|
-
tokenBucket = { date: key, input: 0, output: 0, cache_read: 0, cache_create: 0 };
|
|
801
|
-
dailyTokenMap.set(key, tokenBucket);
|
|
802
|
-
}
|
|
803
|
-
const cacheRead = session.stats.total_cache_read_tokens ?? 0;
|
|
804
|
-
const cacheCreate = session.stats.total_cache_create_tokens ?? 0;
|
|
805
|
-
const pureInput = session.stats.total_input_tokens - cacheRead - cacheCreate;
|
|
806
|
-
tokenBucket.input += Math.max(0, pureInput);
|
|
807
|
-
tokenBucket.output += session.stats.total_output_tokens;
|
|
808
|
-
tokenBucket.cache_read += cacheRead;
|
|
809
|
-
tokenBucket.cache_create += cacheCreate;
|
|
810
|
-
if (session.model_usage) {
|
|
811
|
-
for (const [model, tokens] of Object.entries(session.model_usage)) {
|
|
812
|
-
const entry = modelAgg.get(model);
|
|
813
|
-
if (entry) {
|
|
814
|
-
entry.tokens += tokens;
|
|
815
|
-
entry.sessions += 1;
|
|
816
|
-
} else {
|
|
817
|
-
modelAgg.set(model, { tokens, sessions: 1 });
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
let recentIndex = recentCandidates.length;
|
|
822
|
-
for (let i = 0; i < recentCandidates.length; i += 1) {
|
|
823
|
-
if (activity > recentCandidates[i].activity) {
|
|
824
|
-
recentIndex = i;
|
|
825
|
-
break;
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
if (recentIndex < DASHBOARD_RECENT_LIMIT) {
|
|
829
|
-
recentCandidates.splice(recentIndex, 0, { session, activity });
|
|
830
|
-
if (recentCandidates.length > DASHBOARD_RECENT_LIMIT) recentCandidates.pop();
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
const perAgent = [...agentMetrics.entries()].map(([name, metrics]) => {
|
|
834
|
-
const info = agentInfoMap.get(name);
|
|
835
|
-
return {
|
|
836
|
-
name,
|
|
837
|
-
displayName: info?.displayName ?? name,
|
|
838
|
-
icon: info?.icon ?? "",
|
|
839
|
-
sessions: metrics.sessions,
|
|
840
|
-
messages: metrics.messages,
|
|
841
|
-
tokens: metrics.tokens
|
|
842
|
-
};
|
|
843
|
-
}).filter((item) => item.sessions > 0).sort((a, b) => b.sessions - a.sessions);
|
|
844
|
-
const dailyActivity = [...dailyMap.values()].sort((a, b) => a.date.localeCompare(b.date));
|
|
845
|
-
const dailyTokenActivity = [...dailyTokenMap.values()].sort(
|
|
846
|
-
(a, b) => a.date.localeCompare(b.date)
|
|
847
|
-
);
|
|
848
|
-
const modelDistribution = [...modelAgg.entries()].map(([model, { tokens, sessions: count }]) => ({ model, tokens, sessions: count })).sort((a, b) => b.tokens - a.tokens);
|
|
849
|
-
const recentSessions = recentCandidates.map(({ session }) => {
|
|
850
|
-
const agentKey = getSessionAgentName(session);
|
|
851
|
-
return { ...session, agentName: agentKey };
|
|
726
|
+
const aggregate = buildDashboard(scanResult.sessions, {
|
|
727
|
+
byAgentNames: Object.keys(scanResult.byAgent),
|
|
728
|
+
scope,
|
|
729
|
+
from,
|
|
730
|
+
to,
|
|
731
|
+
agentInfoMap
|
|
852
732
|
});
|
|
853
733
|
const data = {
|
|
854
|
-
|
|
855
|
-
sessions: totalSessions,
|
|
856
|
-
messages: totalMessages,
|
|
857
|
-
tokens: totalTokens,
|
|
858
|
-
cost: totalCost,
|
|
859
|
-
cost_source: totalCost > 0 ? hasEstimatedCost ? "estimated" : "recorded" : void 0,
|
|
860
|
-
latestActivity: latestActivity || void 0
|
|
861
|
-
},
|
|
862
|
-
perAgent,
|
|
863
|
-
dailyActivity,
|
|
864
|
-
dailyTokenActivity,
|
|
865
|
-
modelDistribution,
|
|
866
|
-
recentSessions,
|
|
734
|
+
...aggregate,
|
|
867
735
|
recentFileActivities: listFileActivity({
|
|
868
736
|
agent: scope.agent,
|
|
869
737
|
projectKey: scope.projectKey,
|
|
@@ -1078,112 +946,15 @@ async function createServer(port, store, options = {}) {
|
|
|
1078
946
|
}
|
|
1079
947
|
|
|
1080
948
|
// src/live-scan.ts
|
|
1081
|
-
import { existsSync as
|
|
1082
|
-
import { dirname as dirname2, isAbsolute, join as join2, relative, resolve as resolve2 } from "path";
|
|
949
|
+
import { existsSync as existsSync4 } from "fs";
|
|
1083
950
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1084
951
|
import { Worker } from "worker_threads";
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
952
|
+
|
|
953
|
+
// src/session-watcher.ts
|
|
954
|
+
import { existsSync as existsSync3, readdirSync as readdirSync2, statSync as statSync2, watch } from "fs";
|
|
955
|
+
import { dirname as dirname2, isAbsolute, join as join2, relative, resolve as resolve2 } from "path";
|
|
1088
956
|
var WRITE_STABILITY_THRESHOLD_MS = 250;
|
|
1089
957
|
var WRITE_STABILITY_POLL_MS = 100;
|
|
1090
|
-
var NEW_SESSION_EVENT_WINDOW_MS = 250;
|
|
1091
|
-
var SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD = 100;
|
|
1092
|
-
function sortSessions(sessions) {
|
|
1093
|
-
return [...sessions].sort(
|
|
1094
|
-
(a, b) => (b.time_updated ?? b.time_created) - (a.time_updated ?? a.time_created)
|
|
1095
|
-
);
|
|
1096
|
-
}
|
|
1097
|
-
function sessionSignature(session) {
|
|
1098
|
-
return JSON.stringify([
|
|
1099
|
-
session.title,
|
|
1100
|
-
session.directory,
|
|
1101
|
-
session.time_created,
|
|
1102
|
-
session.time_updated ?? session.time_created,
|
|
1103
|
-
session.stats.message_count,
|
|
1104
|
-
session.stats.total_input_tokens,
|
|
1105
|
-
session.stats.total_output_tokens,
|
|
1106
|
-
session.stats.total_cost,
|
|
1107
|
-
session.stats.total_tokens ?? 0
|
|
1108
|
-
]);
|
|
1109
|
-
}
|
|
1110
|
-
function buildAgentCacheMeta(agent, sessionIds) {
|
|
1111
|
-
const metaMap = agent.getSessionMetaMap?.();
|
|
1112
|
-
const meta = {};
|
|
1113
|
-
if (!metaMap) return meta;
|
|
1114
|
-
for (const [id, data] of metaMap.entries()) {
|
|
1115
|
-
if (sessionIds && !sessionIds.has(id)) continue;
|
|
1116
|
-
meta[id] = { id, ...data };
|
|
1117
|
-
}
|
|
1118
|
-
return meta;
|
|
1119
|
-
}
|
|
1120
|
-
function attachMissingProjectIdentities(sessions) {
|
|
1121
|
-
const identities = /* @__PURE__ */ new Map();
|
|
1122
|
-
return sessions.map((session) => {
|
|
1123
|
-
if (session.project_identity) return session;
|
|
1124
|
-
const directory = session.directory || "";
|
|
1125
|
-
let identity = identities.get(directory);
|
|
1126
|
-
if (!identity) {
|
|
1127
|
-
identity = computeIdentity(directory, realFs);
|
|
1128
|
-
identities.set(directory, identity);
|
|
1129
|
-
}
|
|
1130
|
-
return { ...session, project_identity: identity };
|
|
1131
|
-
});
|
|
1132
|
-
}
|
|
1133
|
-
function buildRefreshDiff(agentName, previousSessions, nextSessions, candidateChangedIds = []) {
|
|
1134
|
-
const previousMap = new Map(previousSessions.map((session) => [session.id, session]));
|
|
1135
|
-
const nextMap = new Map(nextSessions.map((session) => [session.id, session]));
|
|
1136
|
-
const candidateChangedIdSet = new Set(candidateChangedIds);
|
|
1137
|
-
const changedSessions = [];
|
|
1138
|
-
const removedSessionIds = [];
|
|
1139
|
-
let newSessions = 0;
|
|
1140
|
-
let updatedSessions = 0;
|
|
1141
|
-
let removedSessions = 0;
|
|
1142
|
-
nextSessions.forEach((session, index) => {
|
|
1143
|
-
const id = session.id;
|
|
1144
|
-
const previous = previousMap.get(id);
|
|
1145
|
-
if (!previous) {
|
|
1146
|
-
newSessions += 1;
|
|
1147
|
-
changedSessions.push({ session, sortIndex: index });
|
|
1148
|
-
return;
|
|
1149
|
-
}
|
|
1150
|
-
const hasSignatureChange = sessionSignature(previous) !== sessionSignature(session);
|
|
1151
|
-
const hasContentChange = candidateChangedIdSet.has(id);
|
|
1152
|
-
if (hasSignatureChange || hasContentChange) {
|
|
1153
|
-
updatedSessions += 1;
|
|
1154
|
-
}
|
|
1155
|
-
if (hasContentChange || hasSignatureChange) {
|
|
1156
|
-
changedSessions.push({ session, sortIndex: index });
|
|
1157
|
-
}
|
|
1158
|
-
});
|
|
1159
|
-
for (const id of previousMap.keys()) {
|
|
1160
|
-
if (!nextMap.has(id)) {
|
|
1161
|
-
removedSessions += 1;
|
|
1162
|
-
removedSessionIds.push(id);
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1165
|
-
if (newSessions === 0 && updatedSessions === 0 && removedSessions === 0) {
|
|
1166
|
-
return { event: null, changedSessions, removedSessionIds };
|
|
1167
|
-
}
|
|
1168
|
-
return {
|
|
1169
|
-
changedSessions,
|
|
1170
|
-
removedSessionIds,
|
|
1171
|
-
event: {
|
|
1172
|
-
type: "sessions-updated",
|
|
1173
|
-
changedAgents: [agentName],
|
|
1174
|
-
newSessions,
|
|
1175
|
-
updatedSessions,
|
|
1176
|
-
removedSessions,
|
|
1177
|
-
totalSessions: nextSessions.length,
|
|
1178
|
-
timestamp: Date.now(),
|
|
1179
|
-
changedSessionHeads: changedSessions.map(({ session }) => ({ agentName, session })),
|
|
1180
|
-
removedSessionRefs: removedSessionIds.map((sessionId) => ({ agentName, sessionId }))
|
|
1181
|
-
}
|
|
1182
|
-
};
|
|
1183
|
-
}
|
|
1184
|
-
function restoreAgentCacheMeta(agent, meta) {
|
|
1185
|
-
agent.setSessionMetaMap?.(new Map(Object.entries(meta)));
|
|
1186
|
-
}
|
|
1187
958
|
function toAbsolutePath(path) {
|
|
1188
959
|
return isAbsolute(path) ? path : resolve2(path);
|
|
1189
960
|
}
|
|
@@ -1225,36 +996,6 @@ function isSameOrChildPath(parentPath, childPath) {
|
|
|
1225
996
|
function isRelatedPath(changedPath, targetPath) {
|
|
1226
997
|
return isSameOrChildPath(targetPath, changedPath) || isSameOrChildPath(changedPath, targetPath);
|
|
1227
998
|
}
|
|
1228
|
-
function mergeEvents(previous, next) {
|
|
1229
|
-
const changedSessionHeads = /* @__PURE__ */ new Map();
|
|
1230
|
-
const removedSessionRefs = /* @__PURE__ */ new Map();
|
|
1231
|
-
const sessionKey = (agentName, sessionId) => `${agentName}\0${sessionId}`;
|
|
1232
|
-
const addChanged = (item) => {
|
|
1233
|
-
const key = sessionKey(item.agentName, item.session.id);
|
|
1234
|
-
removedSessionRefs.delete(key);
|
|
1235
|
-
changedSessionHeads.set(key, item);
|
|
1236
|
-
};
|
|
1237
|
-
const addRemoved = (item) => {
|
|
1238
|
-
const key = sessionKey(item.agentName, item.sessionId);
|
|
1239
|
-
changedSessionHeads.delete(key);
|
|
1240
|
-
removedSessionRefs.set(key, item);
|
|
1241
|
-
};
|
|
1242
|
-
for (const item of previous.changedSessionHeads) addChanged(item);
|
|
1243
|
-
for (const item of previous.removedSessionRefs) addRemoved(item);
|
|
1244
|
-
for (const item of next.changedSessionHeads) addChanged(item);
|
|
1245
|
-
for (const item of next.removedSessionRefs) addRemoved(item);
|
|
1246
|
-
return {
|
|
1247
|
-
type: "sessions-updated",
|
|
1248
|
-
changedAgents: Array.from(/* @__PURE__ */ new Set([...previous.changedAgents, ...next.changedAgents])),
|
|
1249
|
-
newSessions: previous.newSessions + next.newSessions,
|
|
1250
|
-
updatedSessions: previous.updatedSessions + next.updatedSessions,
|
|
1251
|
-
removedSessions: previous.removedSessions + next.removedSessions,
|
|
1252
|
-
totalSessions: next.totalSessions,
|
|
1253
|
-
timestamp: next.timestamp,
|
|
1254
|
-
changedSessionHeads: [...changedSessionHeads.values()],
|
|
1255
|
-
removedSessionRefs: [...removedSessionRefs.values()]
|
|
1256
|
-
};
|
|
1257
|
-
}
|
|
1258
999
|
function mergeScopes(target, scopes) {
|
|
1259
1000
|
for (const scope of scopes) {
|
|
1260
1001
|
if (!target.some(
|
|
@@ -1312,165 +1053,446 @@ function resolveAgentWatchTargets(agentName) {
|
|
|
1312
1053
|
return [];
|
|
1313
1054
|
}
|
|
1314
1055
|
}
|
|
1315
|
-
var
|
|
1316
|
-
constructor(watchEnabled = true, scanOptions = {}, startupScanOptions = {}, storeOptions = {}) {
|
|
1317
|
-
this.watchEnabled = watchEnabled;
|
|
1318
|
-
this.scanOptions = scanOptions;
|
|
1319
|
-
this.startupScanOptions = startupScanOptions;
|
|
1320
|
-
this.storeOptions = storeOptions;
|
|
1321
|
-
}
|
|
1322
|
-
watchEnabled;
|
|
1323
|
-
scanOptions;
|
|
1324
|
-
startupScanOptions;
|
|
1325
|
-
storeOptions;
|
|
1326
|
-
agents = [];
|
|
1327
|
-
byAgent = {};
|
|
1328
|
-
sessions = [];
|
|
1329
|
-
listeners = /* @__PURE__ */ new Set();
|
|
1330
|
-
scanStatusListeners = /* @__PURE__ */ new Set();
|
|
1331
|
-
scanStatus = {
|
|
1332
|
-
active: false,
|
|
1333
|
-
phase: "idle",
|
|
1334
|
-
pendingAgents: [],
|
|
1335
|
-
scanningAgents: [],
|
|
1336
|
-
completedAgents: [],
|
|
1337
|
-
agentStatuses: {},
|
|
1338
|
-
totalAgents: 0,
|
|
1339
|
-
updatedAt: Date.now()
|
|
1340
|
-
};
|
|
1341
|
-
refreshTimers = /* @__PURE__ */ new Map();
|
|
1342
|
-
refreshTimestamps = /* @__PURE__ */ new Map();
|
|
1343
|
-
refreshInFlight = /* @__PURE__ */ new Set();
|
|
1344
|
-
pendingRefreshes = /* @__PURE__ */ new Set();
|
|
1345
|
-
pendingRefreshPathCounts = /* @__PURE__ */ new Map();
|
|
1056
|
+
var SessionWatcher = class {
|
|
1346
1057
|
watchers = [];
|
|
1347
1058
|
fallbackWatchScopes = /* @__PURE__ */ new Map();
|
|
1348
1059
|
stablePaths = /* @__PURE__ */ new Map();
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
pendingSearchIndexJobs = [];
|
|
1354
|
-
shuttingDown = false;
|
|
1355
|
-
async initialize() {
|
|
1356
|
-
const startedAt = performance.now();
|
|
1357
|
-
const deferInitialRefresh = this.storeOptions.deferInitialRefresh === true;
|
|
1358
|
-
appLogger.info("scan.initial.start", {
|
|
1359
|
-
watch_enabled: this.watchEnabled,
|
|
1360
|
-
agents: this.scanOptions.agents,
|
|
1361
|
-
use_cache: this.scanOptions.useCache ?? true,
|
|
1362
|
-
startup_from: this.startupScanOptions.from,
|
|
1363
|
-
startup_to: this.startupScanOptions.to,
|
|
1364
|
-
deferred: deferInitialRefresh || void 0
|
|
1365
|
-
});
|
|
1366
|
-
const initialResult = await scanSessions({
|
|
1367
|
-
...this.scanOptions,
|
|
1368
|
-
...deferInitialRefresh ? this.startupScanOptions : {},
|
|
1369
|
-
useCache: this.scanOptions.useCache ?? true,
|
|
1370
|
-
smartRefresh: false,
|
|
1371
|
-
cacheOnly: deferInitialRefresh,
|
|
1372
|
-
writeCache: deferInitialRefresh ? false : this.scanOptions.writeCache,
|
|
1373
|
-
smartTagWorkerUrl: this.getSmartTagWorkerUrl() ?? void 0,
|
|
1374
|
-
includeSmartTags: deferInitialRefresh ? false : void 0
|
|
1375
|
-
});
|
|
1376
|
-
this.applyScanResult(initialResult);
|
|
1377
|
-
const indexStartedAt = performance.now();
|
|
1378
|
-
if (!deferInitialRefresh) {
|
|
1379
|
-
await this.enqueueSearchIndexJobs(
|
|
1380
|
-
"scan.initial",
|
|
1381
|
-
this.buildFullSearchIndexJobs("scan.initial")
|
|
1382
|
-
);
|
|
1383
|
-
}
|
|
1384
|
-
const indexDuration = performance.now() - indexStartedAt;
|
|
1385
|
-
appLogger.info("scan.initial.done", {
|
|
1386
|
-
duration_ms: Math.round(performance.now() - startedAt),
|
|
1387
|
-
index_ms: deferInitialRefresh ? void 0 : Math.round(indexDuration),
|
|
1388
|
-
deferred: deferInitialRefresh || void 0,
|
|
1389
|
-
sessions: this.sessions.length,
|
|
1390
|
-
agents: Object.fromEntries(
|
|
1391
|
-
Object.entries(this.byAgent).map(([key, value]) => [key, value.length])
|
|
1392
|
-
),
|
|
1393
|
-
agent_timings: initialResult.timings ? Object.fromEntries(
|
|
1394
|
-
Object.entries(initialResult.timings).map(([name, t]) => [
|
|
1395
|
-
name,
|
|
1396
|
-
{
|
|
1397
|
-
total_ms: Math.round(t.total),
|
|
1398
|
-
cache_load_ms: t.cacheLoad != null ? Math.round(t.cacheLoad) : void 0,
|
|
1399
|
-
check_changes_ms: t.checkChanges != null ? Math.round(t.checkChanges) : void 0,
|
|
1400
|
-
scan_ms: t.scan != null ? Math.round(t.scan) : void 0,
|
|
1401
|
-
identity_ms: t.identity != null ? Math.round(t.identity) : void 0,
|
|
1402
|
-
tags_ms: t.tags != null ? Math.round(t.tags) : void 0
|
|
1403
|
-
}
|
|
1404
|
-
])
|
|
1405
|
-
) : void 0
|
|
1406
|
-
});
|
|
1407
|
-
if (this.watchEnabled) {
|
|
1408
|
-
this.startWatching();
|
|
1409
|
-
}
|
|
1410
|
-
}
|
|
1411
|
-
startBackgroundRefresh() {
|
|
1412
|
-
if (this.backgroundRefreshTimer) {
|
|
1413
|
-
return;
|
|
1414
|
-
}
|
|
1415
|
-
const agentNames = this.agents.map((agent) => agent.name);
|
|
1416
|
-
this.startScanBatch(agentNames, "scanning");
|
|
1417
|
-
this.backgroundRefreshTimer = setTimeout(() => {
|
|
1418
|
-
this.backgroundRefreshTimer = null;
|
|
1419
|
-
for (const agentName of agentNames) {
|
|
1420
|
-
this.scheduleRefresh(agentName, 0);
|
|
1421
|
-
}
|
|
1422
|
-
if (agentNames.length === 0) {
|
|
1423
|
-
this.finishScanBatch();
|
|
1424
|
-
}
|
|
1425
|
-
}, 0);
|
|
1426
|
-
}
|
|
1427
|
-
getSnapshot() {
|
|
1428
|
-
return {
|
|
1429
|
-
sessions: this.sessions,
|
|
1430
|
-
byAgent: this.byAgent,
|
|
1431
|
-
agents: this.agents
|
|
1432
|
-
};
|
|
1433
|
-
}
|
|
1434
|
-
getScanStatus() {
|
|
1435
|
-
return {
|
|
1436
|
-
type: "scan-status",
|
|
1437
|
-
...this.scanStatus,
|
|
1438
|
-
pendingAgents: [...this.scanStatus.pendingAgents],
|
|
1439
|
-
scanningAgents: [...this.scanStatus.scanningAgents],
|
|
1440
|
-
completedAgents: [...this.scanStatus.completedAgents],
|
|
1441
|
-
agentStatuses: Object.fromEntries(
|
|
1442
|
-
Object.entries(this.scanStatus.agentStatuses).map(([agentName, status]) => [
|
|
1443
|
-
agentName,
|
|
1444
|
-
{ ...status }
|
|
1445
|
-
])
|
|
1446
|
-
)
|
|
1447
|
-
};
|
|
1448
|
-
}
|
|
1449
|
-
subscribe(listener) {
|
|
1450
|
-
this.listeners.add(listener);
|
|
1451
|
-
return () => {
|
|
1452
|
-
this.listeners.delete(listener);
|
|
1453
|
-
};
|
|
1454
|
-
}
|
|
1455
|
-
subscribeScanStatus(listener) {
|
|
1456
|
-
this.scanStatusListeners.add(listener);
|
|
1060
|
+
listeners = /* @__PURE__ */ new Set();
|
|
1061
|
+
/** Register a listener fired (after write-stability polling) with the changed agent set. */
|
|
1062
|
+
onAgentsChanged(cb) {
|
|
1063
|
+
this.listeners.add(cb);
|
|
1457
1064
|
return () => {
|
|
1458
|
-
this.
|
|
1065
|
+
this.listeners.delete(cb);
|
|
1459
1066
|
};
|
|
1460
1067
|
}
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1068
|
+
/** Begin watching the given agent names' data directories. */
|
|
1069
|
+
start(agentNames) {
|
|
1070
|
+
const scopesByRoot = /* @__PURE__ */ new Map();
|
|
1071
|
+
for (const agentName of agentNames) {
|
|
1072
|
+
const watchTargets = resolveAgentWatchTargets(agentName);
|
|
1073
|
+
if (watchTargets.length === 0) {
|
|
1074
|
+
appLogger.debug("watch.skip", { agent: agentName });
|
|
1075
|
+
continue;
|
|
1076
|
+
}
|
|
1077
|
+
for (const target of watchTargets) {
|
|
1078
|
+
const watchRootPath = closestWatchablePath(target.root ?? target.path);
|
|
1079
|
+
if (!watchRootPath) continue;
|
|
1080
|
+
let rootPath;
|
|
1081
|
+
try {
|
|
1082
|
+
rootPath = getWatchRoot(watchRootPath);
|
|
1083
|
+
} catch (error) {
|
|
1084
|
+
this.reportWatchError("watch.resolve.error", { path: watchRootPath, error });
|
|
1085
|
+
continue;
|
|
1086
|
+
}
|
|
1087
|
+
const targetPath = toAbsolutePath(target.path);
|
|
1088
|
+
const scopes = scopesByRoot.get(rootPath) ?? [];
|
|
1089
|
+
if (!scopes.some((scope) => scope.agentName === agentName && scope.targetPath === targetPath)) {
|
|
1090
|
+
scopes.push({ agentName, targetPath });
|
|
1091
|
+
}
|
|
1092
|
+
scopesByRoot.set(rootPath, scopes);
|
|
1471
1093
|
}
|
|
1472
1094
|
}
|
|
1473
|
-
|
|
1095
|
+
for (const [rootPath, scopes] of scopesByRoot.entries()) {
|
|
1096
|
+
const agents = Array.from(new Set(scopes.map((scope) => scope.agentName)));
|
|
1097
|
+
appLogger.info("watch.start", {
|
|
1098
|
+
root: rootPath,
|
|
1099
|
+
agents,
|
|
1100
|
+
targets: scopes.map((scope) => ({
|
|
1101
|
+
agent: scope.agentName,
|
|
1102
|
+
path: scope.targetPath
|
|
1103
|
+
}))
|
|
1104
|
+
});
|
|
1105
|
+
if (isRecursiveWatchSupported()) {
|
|
1106
|
+
const started = this.watchDirectory(rootPath, scopes, true);
|
|
1107
|
+
if (started) {
|
|
1108
|
+
continue;
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
this.watchDirectoryTree(rootPath, scopes);
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
/** Stop all watchers and clear pending stability polls. */
|
|
1115
|
+
async dispose() {
|
|
1116
|
+
for (const state of this.stablePaths.values()) {
|
|
1117
|
+
if (state.timer) {
|
|
1118
|
+
clearTimeout(state.timer);
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
this.stablePaths.clear();
|
|
1122
|
+
await Promise.all(this.watchers.map((watcher) => watcher.close()));
|
|
1123
|
+
this.watchers = [];
|
|
1124
|
+
this.fallbackWatchScopes.clear();
|
|
1125
|
+
this.listeners.clear();
|
|
1126
|
+
}
|
|
1127
|
+
watchDirectory(path, scopes, recursive) {
|
|
1128
|
+
try {
|
|
1129
|
+
const watcher = watch(path, { recursive }, (eventType, filename) => {
|
|
1130
|
+
queueMicrotask(() => {
|
|
1131
|
+
try {
|
|
1132
|
+
const activeScopes = recursive ? scopes : this.fallbackWatchScopes.get(path) ?? scopes;
|
|
1133
|
+
this.handleWatchEvent(path, activeScopes, eventType, filename);
|
|
1134
|
+
if (!recursive) {
|
|
1135
|
+
this.watchNewDirectories(path, filename, activeScopes);
|
|
1136
|
+
}
|
|
1137
|
+
} catch (error) {
|
|
1138
|
+
this.reportWatchError("watch.event.error", { path, recursive, error });
|
|
1139
|
+
}
|
|
1140
|
+
});
|
|
1141
|
+
});
|
|
1142
|
+
watcher.on("error", (error) => {
|
|
1143
|
+
this.reportWatchError("watch.error", { path, recursive, error });
|
|
1144
|
+
});
|
|
1145
|
+
this.watchers.push(watcher);
|
|
1146
|
+
return true;
|
|
1147
|
+
} catch (error) {
|
|
1148
|
+
if (recursive && isRecursiveWatchUnavailable(error)) {
|
|
1149
|
+
appLogger.warn("watch.recursive_unavailable", { path, error });
|
|
1150
|
+
return false;
|
|
1151
|
+
}
|
|
1152
|
+
this.reportWatchError("watch.start.error", { path, recursive, error });
|
|
1153
|
+
return false;
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
watchDirectoryTree(rootPath, scopes) {
|
|
1157
|
+
const pending = [rootPath];
|
|
1158
|
+
while (pending.length > 0) {
|
|
1159
|
+
const dirPath = pending.pop();
|
|
1160
|
+
this.watchFallbackDirectory(dirPath, scopes);
|
|
1161
|
+
try {
|
|
1162
|
+
for (const entry of readdirSync2(dirPath, { withFileTypes: true })) {
|
|
1163
|
+
if (entry.isDirectory()) {
|
|
1164
|
+
pending.push(join2(dirPath, entry.name));
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
} catch (error) {
|
|
1168
|
+
this.reportWatchError("watch.scan.error", { path: dirPath, error });
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
watchFallbackDirectory(path, scopes) {
|
|
1173
|
+
const existingScopes = this.fallbackWatchScopes.get(path);
|
|
1174
|
+
if (existingScopes) {
|
|
1175
|
+
mergeScopes(existingScopes, scopes);
|
|
1176
|
+
return;
|
|
1177
|
+
}
|
|
1178
|
+
const storedScopes = [...scopes];
|
|
1179
|
+
this.fallbackWatchScopes.set(path, storedScopes);
|
|
1180
|
+
if (!this.watchDirectory(path, storedScopes, false)) {
|
|
1181
|
+
this.fallbackWatchScopes.delete(path);
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
watchNewDirectories(watchPath, filename, scopes) {
|
|
1185
|
+
const path = resolveWatchEventPath(watchPath, filename);
|
|
1186
|
+
try {
|
|
1187
|
+
if (statSync2(path).isDirectory()) {
|
|
1188
|
+
this.watchDirectoryTree(path, scopes);
|
|
1189
|
+
}
|
|
1190
|
+
} catch {
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
handleWatchEvent(watchPath, scopes, eventType, filename) {
|
|
1194
|
+
const changedPath = resolveWatchEventPath(watchPath, filename);
|
|
1195
|
+
const agentNames = new Set(
|
|
1196
|
+
scopes.filter((scope) => isRelatedPath(changedPath, scope.targetPath)).map((scope) => scope.agentName)
|
|
1197
|
+
);
|
|
1198
|
+
if (agentNames.size === 0) {
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
appLogger.debug("watch.event", {
|
|
1202
|
+
event: eventType,
|
|
1203
|
+
path: changedPath,
|
|
1204
|
+
agents: Array.from(agentNames)
|
|
1205
|
+
});
|
|
1206
|
+
this.waitForStablePath(changedPath, agentNames);
|
|
1207
|
+
}
|
|
1208
|
+
waitForStablePath(path, agentNames) {
|
|
1209
|
+
const existing = this.stablePaths.get(path);
|
|
1210
|
+
if (existing) {
|
|
1211
|
+
for (const agentName of agentNames) {
|
|
1212
|
+
existing.agentNames.add(agentName);
|
|
1213
|
+
}
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
const state = {
|
|
1217
|
+
path,
|
|
1218
|
+
agentNames: new Set(agentNames),
|
|
1219
|
+
lastMtimeMs: null,
|
|
1220
|
+
lastSize: null,
|
|
1221
|
+
stableSince: Date.now(),
|
|
1222
|
+
timer: null
|
|
1223
|
+
};
|
|
1224
|
+
this.stablePaths.set(path, state);
|
|
1225
|
+
this.pollStablePath(path);
|
|
1226
|
+
}
|
|
1227
|
+
pollStablePath(path) {
|
|
1228
|
+
const state = this.stablePaths.get(path);
|
|
1229
|
+
if (!state) {
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1232
|
+
let size;
|
|
1233
|
+
let mtimeMs;
|
|
1234
|
+
try {
|
|
1235
|
+
const stat = statSync2(path);
|
|
1236
|
+
size = stat.size;
|
|
1237
|
+
mtimeMs = stat.mtimeMs;
|
|
1238
|
+
} catch {
|
|
1239
|
+
this.stablePaths.delete(path);
|
|
1240
|
+
this.emitAgentsChanged(state.agentNames);
|
|
1241
|
+
return;
|
|
1242
|
+
}
|
|
1243
|
+
const now = Date.now();
|
|
1244
|
+
const unchanged = state.lastSize === size && state.lastMtimeMs === mtimeMs;
|
|
1245
|
+
if (!unchanged) {
|
|
1246
|
+
state.lastSize = size;
|
|
1247
|
+
state.lastMtimeMs = mtimeMs;
|
|
1248
|
+
state.stableSince = now;
|
|
1249
|
+
}
|
|
1250
|
+
if (unchanged && now - state.stableSince >= WRITE_STABILITY_THRESHOLD_MS) {
|
|
1251
|
+
this.stablePaths.delete(path);
|
|
1252
|
+
this.emitAgentsChanged(state.agentNames);
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
state.timer = setTimeout(() => this.pollStablePath(path), WRITE_STABILITY_POLL_MS);
|
|
1256
|
+
}
|
|
1257
|
+
emitAgentsChanged(agentNames) {
|
|
1258
|
+
if (agentNames.size === 0) return;
|
|
1259
|
+
for (const listener of this.listeners) {
|
|
1260
|
+
listener(new Set(agentNames));
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
reportWatchError(event, data) {
|
|
1264
|
+
appLogger.error(event, data);
|
|
1265
|
+
console.error("[watch] File watcher failed:", data.error);
|
|
1266
|
+
}
|
|
1267
|
+
};
|
|
1268
|
+
|
|
1269
|
+
// src/live-scan.ts
|
|
1270
|
+
var REFRESH_DEBOUNCE_MS = 200;
|
|
1271
|
+
var EMPTY_AGENT_REFRESH_DEBOUNCE_MS = 3e4;
|
|
1272
|
+
var PENDING_REFRESH_DELAY_MS = 100;
|
|
1273
|
+
var NEW_SESSION_EVENT_WINDOW_MS = 250;
|
|
1274
|
+
var SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD = 100;
|
|
1275
|
+
function buildRefreshDiff(agentName, previousSessions, nextSessions, candidateChangedIds = []) {
|
|
1276
|
+
const { changes, removedSessionIds, counts } = computeSessionDiff(
|
|
1277
|
+
previousSessions,
|
|
1278
|
+
nextSessions,
|
|
1279
|
+
candidateChangedIds,
|
|
1280
|
+
sessionSignature
|
|
1281
|
+
);
|
|
1282
|
+
if (counts.new === 0 && counts.updated === 0 && counts.removed === 0) {
|
|
1283
|
+
return { event: null, changedSessions: changes, removedSessionIds };
|
|
1284
|
+
}
|
|
1285
|
+
return {
|
|
1286
|
+
changedSessions: changes,
|
|
1287
|
+
removedSessionIds,
|
|
1288
|
+
event: {
|
|
1289
|
+
type: "sessions-updated",
|
|
1290
|
+
changedAgents: [agentName],
|
|
1291
|
+
newSessions: counts.new,
|
|
1292
|
+
updatedSessions: counts.updated,
|
|
1293
|
+
removedSessions: counts.removed,
|
|
1294
|
+
totalSessions: nextSessions.length,
|
|
1295
|
+
timestamp: Date.now(),
|
|
1296
|
+
changedSessionHeads: changes.map(({ session }) => ({ agentName, session })),
|
|
1297
|
+
removedSessionRefs: removedSessionIds.map((sessionId) => ({ agentName, sessionId }))
|
|
1298
|
+
}
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
function restoreAgentCacheMeta(agent, meta) {
|
|
1302
|
+
agent.setSessionMetaMap(new Map(Object.entries(meta)));
|
|
1303
|
+
}
|
|
1304
|
+
function mergeEvents(previous, next) {
|
|
1305
|
+
const changedSessionHeads = /* @__PURE__ */ new Map();
|
|
1306
|
+
const removedSessionRefs = /* @__PURE__ */ new Map();
|
|
1307
|
+
const sessionKey = (agentName, sessionId) => `${agentName}\0${sessionId}`;
|
|
1308
|
+
const addChanged = (item) => {
|
|
1309
|
+
const key = sessionKey(item.agentName, item.session.id);
|
|
1310
|
+
removedSessionRefs.delete(key);
|
|
1311
|
+
changedSessionHeads.set(key, item);
|
|
1312
|
+
};
|
|
1313
|
+
const addRemoved = (item) => {
|
|
1314
|
+
const key = sessionKey(item.agentName, item.sessionId);
|
|
1315
|
+
changedSessionHeads.delete(key);
|
|
1316
|
+
removedSessionRefs.set(key, item);
|
|
1317
|
+
};
|
|
1318
|
+
for (const item of previous.changedSessionHeads) addChanged(item);
|
|
1319
|
+
for (const item of previous.removedSessionRefs) addRemoved(item);
|
|
1320
|
+
for (const item of next.changedSessionHeads) addChanged(item);
|
|
1321
|
+
for (const item of next.removedSessionRefs) addRemoved(item);
|
|
1322
|
+
return {
|
|
1323
|
+
type: "sessions-updated",
|
|
1324
|
+
changedAgents: Array.from(/* @__PURE__ */ new Set([...previous.changedAgents, ...next.changedAgents])),
|
|
1325
|
+
newSessions: previous.newSessions + next.newSessions,
|
|
1326
|
+
updatedSessions: previous.updatedSessions + next.updatedSessions,
|
|
1327
|
+
removedSessions: previous.removedSessions + next.removedSessions,
|
|
1328
|
+
totalSessions: next.totalSessions,
|
|
1329
|
+
timestamp: next.timestamp,
|
|
1330
|
+
changedSessionHeads: [...changedSessionHeads.values()],
|
|
1331
|
+
removedSessionRefs: [...removedSessionRefs.values()]
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
var LiveScanStore = class {
|
|
1335
|
+
constructor(watchEnabled = true, scanOptions = {}, startupScanOptions = {}, storeOptions = {}) {
|
|
1336
|
+
this.watchEnabled = watchEnabled;
|
|
1337
|
+
this.scanOptions = scanOptions;
|
|
1338
|
+
this.startupScanOptions = startupScanOptions;
|
|
1339
|
+
this.storeOptions = storeOptions;
|
|
1340
|
+
}
|
|
1341
|
+
watchEnabled;
|
|
1342
|
+
scanOptions;
|
|
1343
|
+
startupScanOptions;
|
|
1344
|
+
storeOptions;
|
|
1345
|
+
agents = [];
|
|
1346
|
+
byAgent = {};
|
|
1347
|
+
sessions = [];
|
|
1348
|
+
listeners = /* @__PURE__ */ new Set();
|
|
1349
|
+
scanStatusListeners = /* @__PURE__ */ new Set();
|
|
1350
|
+
scanStatus = {
|
|
1351
|
+
active: false,
|
|
1352
|
+
phase: "idle",
|
|
1353
|
+
pendingAgents: [],
|
|
1354
|
+
scanningAgents: [],
|
|
1355
|
+
completedAgents: [],
|
|
1356
|
+
agentStatuses: {},
|
|
1357
|
+
totalAgents: 0,
|
|
1358
|
+
updatedAt: Date.now()
|
|
1359
|
+
};
|
|
1360
|
+
refreshTimers = /* @__PURE__ */ new Map();
|
|
1361
|
+
refreshTimestamps = /* @__PURE__ */ new Map();
|
|
1362
|
+
refreshInFlight = /* @__PURE__ */ new Set();
|
|
1363
|
+
pendingRefreshes = /* @__PURE__ */ new Set();
|
|
1364
|
+
pendingRefreshPathCounts = /* @__PURE__ */ new Map();
|
|
1365
|
+
watcher = null;
|
|
1366
|
+
pendingEvent = null;
|
|
1367
|
+
pendingEventTimer = null;
|
|
1368
|
+
backgroundRefreshTimer = null;
|
|
1369
|
+
searchIndexWorker = null;
|
|
1370
|
+
pendingSearchIndexJobs = [];
|
|
1371
|
+
shuttingDown = false;
|
|
1372
|
+
async initialize() {
|
|
1373
|
+
const startedAt = performance.now();
|
|
1374
|
+
const deferInitialRefresh = this.storeOptions.deferInitialRefresh === true;
|
|
1375
|
+
appLogger.info("scan.initial.start", {
|
|
1376
|
+
watch_enabled: this.watchEnabled,
|
|
1377
|
+
agents: this.scanOptions.agents,
|
|
1378
|
+
use_cache: this.scanOptions.useCache ?? true,
|
|
1379
|
+
startup_from: this.startupScanOptions.from,
|
|
1380
|
+
startup_to: this.startupScanOptions.to,
|
|
1381
|
+
deferred: deferInitialRefresh || void 0
|
|
1382
|
+
});
|
|
1383
|
+
const initialResult = await scanSessions({
|
|
1384
|
+
...this.scanOptions,
|
|
1385
|
+
...deferInitialRefresh ? this.startupScanOptions : {},
|
|
1386
|
+
useCache: this.scanOptions.useCache ?? true,
|
|
1387
|
+
smartRefresh: false,
|
|
1388
|
+
cacheOnly: deferInitialRefresh,
|
|
1389
|
+
writeCache: deferInitialRefresh ? false : this.scanOptions.writeCache,
|
|
1390
|
+
smartTagWorkerUrl: this.getSmartTagWorkerUrl() ?? void 0,
|
|
1391
|
+
includeSmartTags: deferInitialRefresh ? false : void 0
|
|
1392
|
+
});
|
|
1393
|
+
this.applyScanResult(initialResult);
|
|
1394
|
+
const indexStartedAt = performance.now();
|
|
1395
|
+
if (!deferInitialRefresh) {
|
|
1396
|
+
await this.enqueueSearchIndexJobs(
|
|
1397
|
+
"scan.initial",
|
|
1398
|
+
this.buildFullSearchIndexJobs("scan.initial")
|
|
1399
|
+
);
|
|
1400
|
+
}
|
|
1401
|
+
const indexDuration = performance.now() - indexStartedAt;
|
|
1402
|
+
appLogger.info("scan.initial.done", {
|
|
1403
|
+
duration_ms: Math.round(performance.now() - startedAt),
|
|
1404
|
+
index_ms: deferInitialRefresh ? void 0 : Math.round(indexDuration),
|
|
1405
|
+
deferred: deferInitialRefresh || void 0,
|
|
1406
|
+
sessions: this.sessions.length,
|
|
1407
|
+
agents: Object.fromEntries(
|
|
1408
|
+
Object.entries(this.byAgent).map(([key, value]) => [key, value.length])
|
|
1409
|
+
),
|
|
1410
|
+
agent_timings: initialResult.timings ? Object.fromEntries(
|
|
1411
|
+
Object.entries(initialResult.timings).map(([name, t]) => [
|
|
1412
|
+
name,
|
|
1413
|
+
{
|
|
1414
|
+
total_ms: Math.round(t.total),
|
|
1415
|
+
cache_load_ms: t.cacheLoad != null ? Math.round(t.cacheLoad) : void 0,
|
|
1416
|
+
check_changes_ms: t.checkChanges != null ? Math.round(t.checkChanges) : void 0,
|
|
1417
|
+
scan_ms: t.scan != null ? Math.round(t.scan) : void 0,
|
|
1418
|
+
identity_ms: t.identity != null ? Math.round(t.identity) : void 0,
|
|
1419
|
+
tags_ms: t.tags != null ? Math.round(t.tags) : void 0
|
|
1420
|
+
}
|
|
1421
|
+
])
|
|
1422
|
+
) : void 0
|
|
1423
|
+
});
|
|
1424
|
+
if (this.watchEnabled) {
|
|
1425
|
+
this.watcher = new SessionWatcher();
|
|
1426
|
+
this.watcher.onAgentsChanged((agentNames) => {
|
|
1427
|
+
for (const agentName of agentNames) {
|
|
1428
|
+
this.pendingRefreshPathCounts.set(
|
|
1429
|
+
agentName,
|
|
1430
|
+
(this.pendingRefreshPathCounts.get(agentName) ?? 0) + 1
|
|
1431
|
+
);
|
|
1432
|
+
const delayMs = (this.byAgent[agentName]?.length ?? 0) === 0 ? EMPTY_AGENT_REFRESH_DEBOUNCE_MS : REFRESH_DEBOUNCE_MS;
|
|
1433
|
+
this.scheduleRefresh(agentName, delayMs);
|
|
1434
|
+
}
|
|
1435
|
+
});
|
|
1436
|
+
this.watcher.start(this.agents.map((agent) => agent.name));
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
startBackgroundRefresh() {
|
|
1440
|
+
if (this.backgroundRefreshTimer) {
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1443
|
+
const agentNames = this.agents.map((agent) => agent.name);
|
|
1444
|
+
this.startScanBatch(agentNames, "scanning");
|
|
1445
|
+
this.backgroundRefreshTimer = setTimeout(() => {
|
|
1446
|
+
this.backgroundRefreshTimer = null;
|
|
1447
|
+
for (const agentName of agentNames) {
|
|
1448
|
+
this.scheduleRefresh(agentName, 0);
|
|
1449
|
+
}
|
|
1450
|
+
if (agentNames.length === 0) {
|
|
1451
|
+
this.finishScanBatch();
|
|
1452
|
+
}
|
|
1453
|
+
}, 0);
|
|
1454
|
+
}
|
|
1455
|
+
getSnapshot() {
|
|
1456
|
+
return {
|
|
1457
|
+
sessions: this.sessions,
|
|
1458
|
+
byAgent: this.byAgent,
|
|
1459
|
+
agents: this.agents
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
getScanStatus() {
|
|
1463
|
+
return {
|
|
1464
|
+
type: "scan-status",
|
|
1465
|
+
...this.scanStatus,
|
|
1466
|
+
pendingAgents: [...this.scanStatus.pendingAgents],
|
|
1467
|
+
scanningAgents: [...this.scanStatus.scanningAgents],
|
|
1468
|
+
completedAgents: [...this.scanStatus.completedAgents],
|
|
1469
|
+
agentStatuses: Object.fromEntries(
|
|
1470
|
+
Object.entries(this.scanStatus.agentStatuses).map(([agentName, status]) => [
|
|
1471
|
+
agentName,
|
|
1472
|
+
{ ...status }
|
|
1473
|
+
])
|
|
1474
|
+
)
|
|
1475
|
+
};
|
|
1476
|
+
}
|
|
1477
|
+
subscribe(listener) {
|
|
1478
|
+
this.listeners.add(listener);
|
|
1479
|
+
return () => {
|
|
1480
|
+
this.listeners.delete(listener);
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1483
|
+
subscribeScanStatus(listener) {
|
|
1484
|
+
this.scanStatusListeners.add(listener);
|
|
1485
|
+
return () => {
|
|
1486
|
+
this.scanStatusListeners.delete(listener);
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1489
|
+
async shutdown() {
|
|
1490
|
+
this.shuttingDown = true;
|
|
1491
|
+
for (const timer of this.refreshTimers.values()) {
|
|
1492
|
+
clearTimeout(timer);
|
|
1493
|
+
}
|
|
1494
|
+
this.refreshTimers.clear();
|
|
1495
|
+
this.pendingRefreshPathCounts.clear();
|
|
1474
1496
|
if (this.pendingEventTimer) {
|
|
1475
1497
|
clearTimeout(this.pendingEventTimer);
|
|
1476
1498
|
this.pendingEventTimer = null;
|
|
@@ -1488,9 +1510,10 @@ var LiveScanStore = class {
|
|
|
1488
1510
|
}
|
|
1489
1511
|
this.pendingSearchIndexJobs = [];
|
|
1490
1512
|
this.pendingEvent = null;
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1513
|
+
if (this.watcher) {
|
|
1514
|
+
await this.watcher.dispose();
|
|
1515
|
+
this.watcher = null;
|
|
1516
|
+
}
|
|
1494
1517
|
}
|
|
1495
1518
|
emit(event) {
|
|
1496
1519
|
if (this.pendingEvent || event.newSessions > 0) {
|
|
@@ -1674,14 +1697,14 @@ var LiveScanStore = class {
|
|
|
1674
1697
|
}
|
|
1675
1698
|
getSearchIndexWorkerUrl() {
|
|
1676
1699
|
const workerUrl = new URL("./search-index-worker.js", import.meta.url);
|
|
1677
|
-
if (workerUrl.protocol === "file:" && !
|
|
1700
|
+
if (workerUrl.protocol === "file:" && !existsSync4(fileURLToPath2(workerUrl))) {
|
|
1678
1701
|
return null;
|
|
1679
1702
|
}
|
|
1680
1703
|
return workerUrl;
|
|
1681
1704
|
}
|
|
1682
1705
|
getSmartTagWorkerUrl() {
|
|
1683
1706
|
const workerUrl = new URL("./smart-tag-worker.js", import.meta.url);
|
|
1684
|
-
if (workerUrl.protocol === "file:" && !
|
|
1707
|
+
if (workerUrl.protocol === "file:" && !existsSync4(fileURLToPath2(workerUrl))) {
|
|
1685
1708
|
return null;
|
|
1686
1709
|
}
|
|
1687
1710
|
return workerUrl;
|
|
@@ -1861,9 +1884,6 @@ var LiveScanStore = class {
|
|
|
1861
1884
|
applyFilters(sessions) {
|
|
1862
1885
|
return filterSessions(sessions, { ...this.scanOptions, ...this.startupScanOptions });
|
|
1863
1886
|
}
|
|
1864
|
-
canSyncSources(agent) {
|
|
1865
|
-
return Boolean(agent.listSessionSources && agent.scanSessionSource);
|
|
1866
|
-
}
|
|
1867
1887
|
async refreshInitialIndex() {
|
|
1868
1888
|
const startedAt = performance.now();
|
|
1869
1889
|
const context = "scan.initial.background";
|
|
@@ -1881,195 +1901,6 @@ var LiveScanStore = class {
|
|
|
1881
1901
|
console.error("[search] Background index sync failed:", error);
|
|
1882
1902
|
}
|
|
1883
1903
|
}
|
|
1884
|
-
startWatching() {
|
|
1885
|
-
const scopesByRoot = /* @__PURE__ */ new Map();
|
|
1886
|
-
for (const agent of this.agents) {
|
|
1887
|
-
const watchTargets = resolveAgentWatchTargets(agent.name);
|
|
1888
|
-
if (watchTargets.length === 0) {
|
|
1889
|
-
appLogger.debug("watch.skip", { agent: agent.name });
|
|
1890
|
-
continue;
|
|
1891
|
-
}
|
|
1892
|
-
for (const target of watchTargets) {
|
|
1893
|
-
const watchRootPath = closestWatchablePath(target.root ?? target.path);
|
|
1894
|
-
if (!watchRootPath) continue;
|
|
1895
|
-
let rootPath;
|
|
1896
|
-
try {
|
|
1897
|
-
rootPath = getWatchRoot(watchRootPath);
|
|
1898
|
-
} catch (error) {
|
|
1899
|
-
this.reportWatchError("watch.resolve.error", { path: watchRootPath, error });
|
|
1900
|
-
continue;
|
|
1901
|
-
}
|
|
1902
|
-
const targetPath = toAbsolutePath(target.path);
|
|
1903
|
-
const scopes = scopesByRoot.get(rootPath) ?? [];
|
|
1904
|
-
if (!scopes.some((scope) => scope.agentName === agent.name && scope.targetPath === targetPath)) {
|
|
1905
|
-
scopes.push({ agentName: agent.name, targetPath });
|
|
1906
|
-
}
|
|
1907
|
-
scopesByRoot.set(rootPath, scopes);
|
|
1908
|
-
}
|
|
1909
|
-
}
|
|
1910
|
-
for (const [rootPath, scopes] of scopesByRoot.entries()) {
|
|
1911
|
-
const agents = Array.from(new Set(scopes.map((scope) => scope.agentName)));
|
|
1912
|
-
appLogger.info("watch.start", {
|
|
1913
|
-
root: rootPath,
|
|
1914
|
-
agents,
|
|
1915
|
-
targets: scopes.map((scope) => ({
|
|
1916
|
-
agent: scope.agentName,
|
|
1917
|
-
path: scope.targetPath
|
|
1918
|
-
}))
|
|
1919
|
-
});
|
|
1920
|
-
if (isRecursiveWatchSupported()) {
|
|
1921
|
-
const started = this.watchDirectory(rootPath, scopes, true);
|
|
1922
|
-
if (started) {
|
|
1923
|
-
continue;
|
|
1924
|
-
}
|
|
1925
|
-
}
|
|
1926
|
-
this.watchDirectoryTree(rootPath, scopes);
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
watchDirectory(path, scopes, recursive) {
|
|
1930
|
-
try {
|
|
1931
|
-
const watcher = watch(path, { recursive }, (eventType, filename) => {
|
|
1932
|
-
queueMicrotask(() => {
|
|
1933
|
-
try {
|
|
1934
|
-
const activeScopes = recursive ? scopes : this.fallbackWatchScopes.get(path) ?? scopes;
|
|
1935
|
-
this.handleWatchEvent(path, activeScopes, eventType, filename);
|
|
1936
|
-
if (!recursive) {
|
|
1937
|
-
this.watchNewDirectories(path, filename, activeScopes);
|
|
1938
|
-
}
|
|
1939
|
-
} catch (error) {
|
|
1940
|
-
this.reportWatchError("watch.event.error", { path, recursive, error });
|
|
1941
|
-
}
|
|
1942
|
-
});
|
|
1943
|
-
});
|
|
1944
|
-
watcher.on("error", (error) => {
|
|
1945
|
-
this.reportWatchError("watch.error", { path, recursive, error });
|
|
1946
|
-
});
|
|
1947
|
-
this.watchers.push(watcher);
|
|
1948
|
-
return true;
|
|
1949
|
-
} catch (error) {
|
|
1950
|
-
if (recursive && isRecursiveWatchUnavailable(error)) {
|
|
1951
|
-
appLogger.warn("watch.recursive_unavailable", { path, error });
|
|
1952
|
-
return false;
|
|
1953
|
-
}
|
|
1954
|
-
this.reportWatchError("watch.start.error", { path, recursive, error });
|
|
1955
|
-
return false;
|
|
1956
|
-
}
|
|
1957
|
-
}
|
|
1958
|
-
watchDirectoryTree(rootPath, scopes) {
|
|
1959
|
-
const pending = [rootPath];
|
|
1960
|
-
while (pending.length > 0) {
|
|
1961
|
-
const dirPath = pending.pop();
|
|
1962
|
-
this.watchFallbackDirectory(dirPath, scopes);
|
|
1963
|
-
try {
|
|
1964
|
-
for (const entry of readdirSync2(dirPath, { withFileTypes: true })) {
|
|
1965
|
-
if (entry.isDirectory()) {
|
|
1966
|
-
pending.push(join2(dirPath, entry.name));
|
|
1967
|
-
}
|
|
1968
|
-
}
|
|
1969
|
-
} catch (error) {
|
|
1970
|
-
this.reportWatchError("watch.scan.error", { path: dirPath, error });
|
|
1971
|
-
}
|
|
1972
|
-
}
|
|
1973
|
-
}
|
|
1974
|
-
watchFallbackDirectory(path, scopes) {
|
|
1975
|
-
const existingScopes = this.fallbackWatchScopes.get(path);
|
|
1976
|
-
if (existingScopes) {
|
|
1977
|
-
mergeScopes(existingScopes, scopes);
|
|
1978
|
-
return;
|
|
1979
|
-
}
|
|
1980
|
-
const storedScopes = [...scopes];
|
|
1981
|
-
this.fallbackWatchScopes.set(path, storedScopes);
|
|
1982
|
-
if (!this.watchDirectory(path, storedScopes, false)) {
|
|
1983
|
-
this.fallbackWatchScopes.delete(path);
|
|
1984
|
-
}
|
|
1985
|
-
}
|
|
1986
|
-
watchNewDirectories(watchPath, filename, scopes) {
|
|
1987
|
-
const path = resolveWatchEventPath(watchPath, filename);
|
|
1988
|
-
try {
|
|
1989
|
-
if (statSync2(path).isDirectory()) {
|
|
1990
|
-
this.watchDirectoryTree(path, scopes);
|
|
1991
|
-
}
|
|
1992
|
-
} catch {
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
|
-
handleWatchEvent(watchPath, scopes, eventType, filename) {
|
|
1996
|
-
const changedPath = resolveWatchEventPath(watchPath, filename);
|
|
1997
|
-
const agentNames = new Set(
|
|
1998
|
-
scopes.filter((scope) => isRelatedPath(changedPath, scope.targetPath)).map((scope) => scope.agentName)
|
|
1999
|
-
);
|
|
2000
|
-
if (agentNames.size === 0) {
|
|
2001
|
-
return;
|
|
2002
|
-
}
|
|
2003
|
-
appLogger.debug("watch.event", {
|
|
2004
|
-
event: eventType,
|
|
2005
|
-
path: changedPath,
|
|
2006
|
-
agents: Array.from(agentNames)
|
|
2007
|
-
});
|
|
2008
|
-
this.waitForStablePath(changedPath, agentNames);
|
|
2009
|
-
}
|
|
2010
|
-
waitForStablePath(path, agentNames) {
|
|
2011
|
-
const existing = this.stablePaths.get(path);
|
|
2012
|
-
if (existing) {
|
|
2013
|
-
for (const agentName of agentNames) {
|
|
2014
|
-
existing.agentNames.add(agentName);
|
|
2015
|
-
}
|
|
2016
|
-
return;
|
|
2017
|
-
}
|
|
2018
|
-
const state = {
|
|
2019
|
-
path,
|
|
2020
|
-
agentNames: new Set(agentNames),
|
|
2021
|
-
lastMtimeMs: null,
|
|
2022
|
-
lastSize: null,
|
|
2023
|
-
stableSince: Date.now(),
|
|
2024
|
-
timer: null
|
|
2025
|
-
};
|
|
2026
|
-
this.stablePaths.set(path, state);
|
|
2027
|
-
this.pollStablePath(path);
|
|
2028
|
-
}
|
|
2029
|
-
pollStablePath(path) {
|
|
2030
|
-
const state = this.stablePaths.get(path);
|
|
2031
|
-
if (!state) {
|
|
2032
|
-
return;
|
|
2033
|
-
}
|
|
2034
|
-
let size;
|
|
2035
|
-
let mtimeMs;
|
|
2036
|
-
try {
|
|
2037
|
-
const stat = statSync2(path);
|
|
2038
|
-
size = stat.size;
|
|
2039
|
-
mtimeMs = stat.mtimeMs;
|
|
2040
|
-
} catch {
|
|
2041
|
-
this.stablePaths.delete(path);
|
|
2042
|
-
this.scheduleRefreshForAgents(state.agentNames);
|
|
2043
|
-
return;
|
|
2044
|
-
}
|
|
2045
|
-
const now = Date.now();
|
|
2046
|
-
const unchanged = state.lastSize === size && state.lastMtimeMs === mtimeMs;
|
|
2047
|
-
if (!unchanged) {
|
|
2048
|
-
state.lastSize = size;
|
|
2049
|
-
state.lastMtimeMs = mtimeMs;
|
|
2050
|
-
state.stableSince = now;
|
|
2051
|
-
}
|
|
2052
|
-
if (unchanged && now - state.stableSince >= WRITE_STABILITY_THRESHOLD_MS) {
|
|
2053
|
-
this.stablePaths.delete(path);
|
|
2054
|
-
this.scheduleRefreshForAgents(state.agentNames);
|
|
2055
|
-
return;
|
|
2056
|
-
}
|
|
2057
|
-
state.timer = setTimeout(() => this.pollStablePath(path), WRITE_STABILITY_POLL_MS);
|
|
2058
|
-
}
|
|
2059
|
-
scheduleRefreshForAgents(agentNames) {
|
|
2060
|
-
for (const agentName of agentNames) {
|
|
2061
|
-
this.pendingRefreshPathCounts.set(
|
|
2062
|
-
agentName,
|
|
2063
|
-
(this.pendingRefreshPathCounts.get(agentName) ?? 0) + 1
|
|
2064
|
-
);
|
|
2065
|
-
const delayMs = (this.byAgent[agentName]?.length ?? 0) === 0 ? EMPTY_AGENT_REFRESH_DEBOUNCE_MS : REFRESH_DEBOUNCE_MS;
|
|
2066
|
-
this.scheduleRefresh(agentName, delayMs);
|
|
2067
|
-
}
|
|
2068
|
-
}
|
|
2069
|
-
reportWatchError(event, data) {
|
|
2070
|
-
appLogger.error(event, data);
|
|
2071
|
-
console.error("[watch] File watcher failed:", data.error);
|
|
2072
|
-
}
|
|
2073
1904
|
scheduleRefresh(agentName, delayMs = REFRESH_DEBOUNCE_MS) {
|
|
2074
1905
|
appLogger.debug("scan.refresh.schedule", { agent: agentName, delay_ms: delayMs });
|
|
2075
1906
|
const existing = this.refreshTimers.get(agentName);
|
|
@@ -2149,7 +1980,7 @@ var LiveScanStore = class {
|
|
|
2149
1980
|
nextSessions = fullScanSessions;
|
|
2150
1981
|
scanDuration = performance.now() - scanStartedAt;
|
|
2151
1982
|
this.refreshTimestamps.set(agentName, Date.now());
|
|
2152
|
-
} else if (cached &&
|
|
1983
|
+
} else if (cached && agent instanceof FileSystemSessionSource) {
|
|
2153
1984
|
const scanStartedAt = performance.now();
|
|
2154
1985
|
const result = await this.scanAgentInWorker(
|
|
2155
1986
|
agent,
|
|
@@ -2162,7 +1993,7 @@ var LiveScanStore = class {
|
|
|
2162
1993
|
}
|
|
2163
1994
|
);
|
|
2164
1995
|
nextSessions = result.sessions;
|
|
2165
|
-
agent.setSessionMetaMap
|
|
1996
|
+
agent.setSessionMetaMap(new Map(Object.entries(result.meta)));
|
|
2166
1997
|
preciseChangedIds = result.changedIds ?? [];
|
|
2167
1998
|
usedIncrementalScan = true;
|
|
2168
1999
|
persistenceDiff = buildRefreshDiff(
|
|
@@ -2179,7 +2010,7 @@ var LiveScanStore = class {
|
|
|
2179
2010
|
duration_ms: Math.round(performance.now() - startedAt)
|
|
2180
2011
|
});
|
|
2181
2012
|
}
|
|
2182
|
-
} else if (refreshBaseline.length > 0
|
|
2013
|
+
} else if (refreshBaseline.length > 0) {
|
|
2183
2014
|
const checkStartedAt = performance.now();
|
|
2184
2015
|
const checkResult = await Promise.resolve(
|
|
2185
2016
|
agent.checkForChanges(cacheTimestamp, refreshBaseline)
|
|
@@ -2212,7 +2043,7 @@ var LiveScanStore = class {
|
|
|
2212
2043
|
const scanStartedAt = performance.now();
|
|
2213
2044
|
const result = await this.scanAgentInWorker(agent, previousSessions, null, {});
|
|
2214
2045
|
nextSessions = result.sessions;
|
|
2215
|
-
agent.setSessionMetaMap
|
|
2046
|
+
agent.setSessionMetaMap(new Map(Object.entries(result.meta)));
|
|
2216
2047
|
fullScanSessions = attachMissingProjectIdentities(nextSessions);
|
|
2217
2048
|
nextSessions = fullScanSessions;
|
|
2218
2049
|
scanDuration = performance.now() - scanStartedAt;
|
|
@@ -2445,7 +2276,7 @@ var main = defineCommand({
|
|
|
2445
2276
|
log_path: appLogger.getLogPath()
|
|
2446
2277
|
});
|
|
2447
2278
|
if (clearCache) {
|
|
2448
|
-
const { clearCache: clear } = await import("./dist-
|
|
2279
|
+
const { clearCache: clear } = await import("./dist-GZSUB4NY.js");
|
|
2449
2280
|
clear();
|
|
2450
2281
|
appLogger.info("cache.clear");
|
|
2451
2282
|
console.log("Cache cleared.");
|