codesesh 0.11.0 → 0.13.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/README.md +7 -1
- package/dist/{chunk-BIXOP5QX.js → chunk-BV65IEWZ.js} +429 -192
- package/dist/chunk-BV65IEWZ.js.map +1 -0
- package/dist/{dist-T737I76S.js → dist-VD54GDPO.js} +22 -2
- package/dist/index.js +1058 -442
- package/dist/index.js.map +1 -1
- package/dist/scan-refresh-worker.js +35 -9
- package/dist/scan-refresh-worker.js.map +1 -1
- package/dist/search-index-worker.js +6 -1
- package/dist/search-index-worker.js.map +1 -1
- package/dist/smart-tag-worker.js +1 -1
- package/dist/web/assets/index-ZikfLnUo.js +113 -0
- package/dist/web/assets/index-y6Zx3LT1.css +2 -0
- package/dist/web/assets/markdown-dR4kAewZ.js +14 -0
- package/dist/web/assets/react-DBHwgW7V.js +1821 -0
- package/dist/web/assets/syntax-C_RLNYQn.js +6 -0
- package/dist/web/assets/vendor-bXsb4Kz4.js +40 -0
- package/dist/web/index.html +6 -6
- package/package.json +9 -8
- package/dist/chunk-BIXOP5QX.js.map +0 -1
- package/dist/web/assets/index-DlZEB-Op.css +0 -2
- package/dist/web/assets/index-O6YSX0s1.js +0 -113
- package/dist/web/assets/markdown-Bm__FT1K.js +0 -14
- package/dist/web/assets/react-CGUTVnhO.js +0 -1821
- package/dist/web/assets/syntax-Cjw-OADI.js +0 -6
- package/dist/web/assets/vendor-CR3FdUHs.js +0 -40
- /package/dist/{dist-T737I76S.js.map → dist-VD54GDPO.js.map} +0 -0
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// ../core/dist/chunk-M5ISIPFR.mjs
|
|
4
|
+
function compareSessionActivityDesc(a, b) {
|
|
5
|
+
return (b.time_updated ?? b.time_created) - (a.time_updated ?? a.time_created);
|
|
6
|
+
}
|
|
7
|
+
function sortSessionsByActivity(sessions) {
|
|
8
|
+
for (let index = 1; index < sessions.length; index += 1) {
|
|
9
|
+
if (compareSessionActivityDesc(sessions[index - 1], sessions[index]) > 0) {
|
|
10
|
+
return [...sessions].sort(compareSessionActivityDesc);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return [...sessions];
|
|
14
|
+
}
|
|
15
|
+
|
|
3
16
|
// ../core/dist/index.mjs
|
|
4
|
-
import { existsSync as existsSync4, readdirSync, readFileSync as
|
|
17
|
+
import { existsSync as existsSync4, readdirSync, readFileSync as readFileSync2, statSync as statSync2 } from "fs";
|
|
5
18
|
import { join as join3, basename as basename2, dirname } from "path";
|
|
6
19
|
import { existsSync, statSync } from "fs";
|
|
7
20
|
import { existsSync as existsSync2 } from "fs";
|
|
8
21
|
import { homedir, platform } from "os";
|
|
9
22
|
import { join } from "path";
|
|
10
|
-
import {
|
|
23
|
+
import { closeSync, openSync, readSync } from "fs";
|
|
24
|
+
import { StringDecoder } from "string_decoder";
|
|
11
25
|
import { basename } from "path";
|
|
12
|
-
import { existsSync as existsSync3, mkdirSync, readFileSync
|
|
26
|
+
import { existsSync as existsSync3, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
13
27
|
import { homedir as homedir2 } from "os";
|
|
14
28
|
import { join as join2 } from "path";
|
|
15
29
|
import { join as join5 } from "path";
|
|
@@ -17,26 +31,26 @@ import { existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
|
|
|
17
31
|
import { basename as basename3, dirname as dirname2, join as join4 } from "path";
|
|
18
32
|
import { createRequire } from "module";
|
|
19
33
|
import { createHash } from "crypto";
|
|
20
|
-
import { existsSync as existsSync6, readFileSync as
|
|
34
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
|
|
21
35
|
import { join as join6, basename as basename4, dirname as dirname3 } from "path";
|
|
22
36
|
import {
|
|
23
|
-
closeSync,
|
|
37
|
+
closeSync as closeSync2,
|
|
24
38
|
existsSync as existsSync7,
|
|
25
|
-
openSync,
|
|
26
|
-
readFileSync as
|
|
27
|
-
readSync,
|
|
39
|
+
openSync as openSync2,
|
|
40
|
+
readFileSync as readFileSync4,
|
|
41
|
+
readSync as readSync2,
|
|
28
42
|
readdirSync as readdirSync3,
|
|
29
43
|
statSync as statSync4
|
|
30
44
|
} from "fs";
|
|
31
45
|
import { join as join7, basename as basename5 } from "path";
|
|
32
|
-
import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as
|
|
46
|
+
import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync5, statSync as statSync5 } from "fs";
|
|
33
47
|
import { join as join8, normalize } from "path";
|
|
34
|
-
import { existsSync as existsSync9, readFileSync as
|
|
48
|
+
import { existsSync as existsSync9, readFileSync as readFileSync6, readdirSync as readdirSync5, statSync as statSync6 } from "fs";
|
|
35
49
|
import { basename as basename6, join as join9 } from "path";
|
|
36
50
|
import { join as join10 } from "path";
|
|
37
51
|
import { availableParallelism } from "os";
|
|
38
52
|
import { Worker } from "worker_threads";
|
|
39
|
-
import { existsSync as existsSync10, readFileSync as
|
|
53
|
+
import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
|
|
40
54
|
import { spawnSync } from "child_process";
|
|
41
55
|
import * as os from "os";
|
|
42
56
|
import * as path from "path";
|
|
@@ -244,6 +258,7 @@ function getZCodeDataPath() {
|
|
|
244
258
|
}
|
|
245
259
|
return null;
|
|
246
260
|
}
|
|
261
|
+
var READ_CHUNK_BYTES = 1 << 20;
|
|
247
262
|
function* parseJsonlLines(content) {
|
|
248
263
|
for (const line of content.split("\n")) {
|
|
249
264
|
const trimmed = line.trim();
|
|
@@ -254,9 +269,35 @@ function* parseJsonlLines(content) {
|
|
|
254
269
|
}
|
|
255
270
|
}
|
|
256
271
|
}
|
|
257
|
-
function
|
|
258
|
-
const
|
|
259
|
-
|
|
272
|
+
function* readJsonlFileLines(filePath, chunkBytes = READ_CHUNK_BYTES) {
|
|
273
|
+
const fd = openSync(filePath, "r");
|
|
274
|
+
try {
|
|
275
|
+
const buffer = Buffer.alloc(chunkBytes);
|
|
276
|
+
const decoder = new StringDecoder("utf8");
|
|
277
|
+
let remainder = "";
|
|
278
|
+
let bytesRead = readSync(fd, buffer, 0, chunkBytes, -1);
|
|
279
|
+
while (bytesRead > 0) {
|
|
280
|
+
const lines = (remainder + decoder.write(buffer.subarray(0, bytesRead))).split("\n");
|
|
281
|
+
remainder = lines.pop();
|
|
282
|
+
for (const line of lines) {
|
|
283
|
+
const trimmed = line.trim();
|
|
284
|
+
if (trimmed) yield trimmed;
|
|
285
|
+
}
|
|
286
|
+
bytesRead = readSync(fd, buffer, 0, chunkBytes, -1);
|
|
287
|
+
}
|
|
288
|
+
const tail = (remainder + decoder.end()).trim();
|
|
289
|
+
if (tail) yield tail;
|
|
290
|
+
} finally {
|
|
291
|
+
closeSync(fd);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function* readJsonlFile(filePath) {
|
|
295
|
+
for (const line of readJsonlFileLines(filePath)) {
|
|
296
|
+
try {
|
|
297
|
+
yield JSON.parse(line);
|
|
298
|
+
} catch {
|
|
299
|
+
}
|
|
300
|
+
}
|
|
260
301
|
}
|
|
261
302
|
var INTERNAL_TAGS = [
|
|
262
303
|
"command-message",
|
|
@@ -638,7 +679,7 @@ function loadDiskCache() {
|
|
|
638
679
|
const path2 = getCachePath();
|
|
639
680
|
if (!existsSync3(path2)) return;
|
|
640
681
|
try {
|
|
641
|
-
const cached = JSON.parse(
|
|
682
|
+
const cached = JSON.parse(readFileSync(path2, "utf-8"));
|
|
642
683
|
if (Date.now() - cached.timestamp <= CACHE_TTL_MS) {
|
|
643
684
|
const next = loadSnapshot();
|
|
644
685
|
for (const [name, rawPricing] of Object.entries(cached.data)) {
|
|
@@ -661,7 +702,7 @@ async function refreshPricingCache() {
|
|
|
661
702
|
const path2 = getCachePath();
|
|
662
703
|
if (existsSync3(path2)) {
|
|
663
704
|
try {
|
|
664
|
-
const cached = JSON.parse(
|
|
705
|
+
const cached = JSON.parse(readFileSync(path2, "utf-8"));
|
|
665
706
|
if (typeof cached.timestamp === "number" && Date.now() - cached.timestamp <= CACHE_TTL_MS) {
|
|
666
707
|
return false;
|
|
667
708
|
}
|
|
@@ -909,11 +950,16 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
909
950
|
perf.end(scanMarker);
|
|
910
951
|
return heads;
|
|
911
952
|
}
|
|
912
|
-
listSessionSources() {
|
|
953
|
+
listSessionSources(options) {
|
|
913
954
|
if (!this.basePath) return [];
|
|
914
955
|
const refs = [];
|
|
915
956
|
for (const projectDir of this.listProjectDirs()) {
|
|
916
957
|
for (const file of this.listJsonlFiles(projectDir)) {
|
|
958
|
+
try {
|
|
959
|
+
if (!matchesScanWindow(statSync2(file).mtimeMs, options)) continue;
|
|
960
|
+
} catch {
|
|
961
|
+
continue;
|
|
962
|
+
}
|
|
917
963
|
const sessionId = basename2(file, ".jsonl");
|
|
918
964
|
refs.push({
|
|
919
965
|
sessionId,
|
|
@@ -940,7 +986,7 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
940
986
|
if (!existsSync4(meta.sourcePath)) {
|
|
941
987
|
throw new Error(`Session file missing: ${meta.sourcePath}`);
|
|
942
988
|
}
|
|
943
|
-
const content =
|
|
989
|
+
const content = readFileSync2(meta.sourcePath, "utf-8");
|
|
944
990
|
const messages = [];
|
|
945
991
|
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
946
992
|
const ignoredToolCallIds = /* @__PURE__ */ new Set();
|
|
@@ -1061,7 +1107,7 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1061
1107
|
const map = /* @__PURE__ */ new Map();
|
|
1062
1108
|
if (existsSync4(indexPath)) {
|
|
1063
1109
|
try {
|
|
1064
|
-
const data = JSON.parse(
|
|
1110
|
+
const data = JSON.parse(readFileSync2(indexPath, "utf-8"));
|
|
1065
1111
|
const entries = data?.entries ?? [];
|
|
1066
1112
|
for (const entry of entries) {
|
|
1067
1113
|
const sid = entry?.sessionId;
|
|
@@ -1080,7 +1126,7 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
|
|
|
1080
1126
|
return getParsedSession(this.parseSessionHeadResult(filePath, projectDir));
|
|
1081
1127
|
}
|
|
1082
1128
|
parseSessionHeadResult(filePath, projectDir) {
|
|
1083
|
-
const content =
|
|
1129
|
+
const content = readFileSync2(filePath, "utf-8");
|
|
1084
1130
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
1085
1131
|
if (lines.length === 0) return skippedSession("empty file");
|
|
1086
1132
|
const sessionId = basename2(filePath, ".jsonl");
|
|
@@ -2137,7 +2183,7 @@ function kimiContentText(content) {
|
|
|
2137
2183
|
}
|
|
2138
2184
|
function extractFirstUserTitle(contextFile, wireFile) {
|
|
2139
2185
|
if (contextFile && existsSync6(contextFile)) {
|
|
2140
|
-
const content =
|
|
2186
|
+
const content = readFileSync3(contextFile, "utf-8");
|
|
2141
2187
|
for (const record of parseJsonlLines(content)) {
|
|
2142
2188
|
if (record.role !== "user") continue;
|
|
2143
2189
|
const title = normalizeTitleText(kimiContentText(record.content));
|
|
@@ -2145,7 +2191,7 @@ function extractFirstUserTitle(contextFile, wireFile) {
|
|
|
2145
2191
|
}
|
|
2146
2192
|
}
|
|
2147
2193
|
if (wireFile && existsSync6(wireFile)) {
|
|
2148
|
-
const content =
|
|
2194
|
+
const content = readFileSync3(wireFile, "utf-8");
|
|
2149
2195
|
for (const record of parseJsonlLines(content)) {
|
|
2150
2196
|
const message = record.message ?? {};
|
|
2151
2197
|
if (message.type !== "TurnBegin") continue;
|
|
@@ -2174,12 +2220,12 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2174
2220
|
const configPath = join6(roots.kimiRoot, "kimi.json");
|
|
2175
2221
|
const tomlPath = join6(roots.kimiRoot, "config.toml");
|
|
2176
2222
|
if (existsSync6(tomlPath)) {
|
|
2177
|
-
const configText =
|
|
2223
|
+
const configText = readFileSync3(tomlPath, "utf-8");
|
|
2178
2224
|
this.defaultModel = configText.match(/^default_model\s*=\s*"([^"]+)"/m)?.[1] ?? null;
|
|
2179
2225
|
}
|
|
2180
2226
|
if (!existsSync6(configPath)) return;
|
|
2181
2227
|
try {
|
|
2182
|
-
const raw = JSON.parse(
|
|
2228
|
+
const raw = JSON.parse(readFileSync3(configPath, "utf-8"));
|
|
2183
2229
|
const workDirs = raw?.work_dirs;
|
|
2184
2230
|
if (!Array.isArray(workDirs)) return;
|
|
2185
2231
|
for (const wd of workDirs) {
|
|
@@ -2243,12 +2289,12 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2243
2289
|
let wireMtime = null;
|
|
2244
2290
|
let metaFile = "";
|
|
2245
2291
|
if (existsSync6(statePath)) {
|
|
2246
|
-
const state = JSON.parse(
|
|
2292
|
+
const state = JSON.parse(readFileSync3(statePath, "utf-8"));
|
|
2247
2293
|
title = String(state.custom_title ?? "");
|
|
2248
2294
|
wireMtime = typeof state.wire_mtime === "number" ? state.wire_mtime : null;
|
|
2249
2295
|
metaFile = statePath;
|
|
2250
2296
|
} else if (existsSync6(metaPath)) {
|
|
2251
|
-
const meta = JSON.parse(
|
|
2297
|
+
const meta = JSON.parse(readFileSync3(metaPath, "utf-8"));
|
|
2252
2298
|
title = String(meta.title ?? "");
|
|
2253
2299
|
wireMtime = typeof meta.wire_mtime === "number" ? meta.wire_mtime : null;
|
|
2254
2300
|
metaFile = metaPath;
|
|
@@ -2316,12 +2362,12 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2316
2362
|
perf.end(scanMarker);
|
|
2317
2363
|
return heads;
|
|
2318
2364
|
}
|
|
2319
|
-
listSessionSources() {
|
|
2365
|
+
listSessionSources(options) {
|
|
2320
2366
|
if (!this.basePath) return [];
|
|
2321
2367
|
const refs = [];
|
|
2322
2368
|
for (const dir of this.listSessionDirs()) {
|
|
2323
2369
|
const meta = getParsedSession(this.parseSessionDirResult(dir));
|
|
2324
|
-
if (!meta) continue;
|
|
2370
|
+
if (!meta || !matchesScanWindow(meta.createdAt, options)) continue;
|
|
2325
2371
|
refs.push({
|
|
2326
2372
|
sessionId: meta.id,
|
|
2327
2373
|
sourcePath: meta.sourcePath,
|
|
@@ -2356,7 +2402,7 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2356
2402
|
}
|
|
2357
2403
|
getSessionDataFromContext(meta) {
|
|
2358
2404
|
if (!meta.contextFile) throw new Error("context.jsonl is missing");
|
|
2359
|
-
const content =
|
|
2405
|
+
const content = readFileSync3(meta.contextFile, "utf-8");
|
|
2360
2406
|
const messages = [];
|
|
2361
2407
|
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
2362
2408
|
const ignoredToolCallIds = /* @__PURE__ */ new Set();
|
|
@@ -2423,7 +2469,7 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2423
2469
|
getSessionDataFromWire(meta) {
|
|
2424
2470
|
const wirePath = meta.wireFile ?? join6(meta.sourcePath, "wire.jsonl");
|
|
2425
2471
|
if (!existsSync6(wirePath)) throw new Error("wire.jsonl is missing");
|
|
2426
|
-
const content =
|
|
2472
|
+
const content = readFileSync3(wirePath, "utf-8");
|
|
2427
2473
|
const messages = [];
|
|
2428
2474
|
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
2429
2475
|
const ignoredToolCallIds = /* @__PURE__ */ new Set();
|
|
@@ -2723,7 +2769,7 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2723
2769
|
const wirePath = join6(sessionDir, "wire.jsonl");
|
|
2724
2770
|
if (!existsSync6(wirePath)) return stats;
|
|
2725
2771
|
try {
|
|
2726
|
-
const content =
|
|
2772
|
+
const content = readFileSync3(wirePath, "utf-8");
|
|
2727
2773
|
for (const line of content.split("\n").filter((l) => l.trim())) {
|
|
2728
2774
|
try {
|
|
2729
2775
|
const data = JSON.parse(line);
|
|
@@ -2747,7 +2793,7 @@ var KimiAgent = class extends FileSystemSessionSource {
|
|
|
2747
2793
|
const rawPath = existsSync6(contextPath) ? contextPath : wirePath;
|
|
2748
2794
|
if (!existsSync6(rawPath)) return stats;
|
|
2749
2795
|
try {
|
|
2750
|
-
const rawContent =
|
|
2796
|
+
const rawContent = readFileSync3(rawPath, "utf-8");
|
|
2751
2797
|
for (const line of rawContent.split("\n").filter((l) => l.trim())) {
|
|
2752
2798
|
try {
|
|
2753
2799
|
const data = JSON.parse(line);
|
|
@@ -2999,10 +3045,10 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
2999
3045
|
perf.end(scanMarker);
|
|
3000
3046
|
return heads;
|
|
3001
3047
|
}
|
|
3002
|
-
listSessionSources() {
|
|
3048
|
+
listSessionSources(options) {
|
|
3003
3049
|
if (!this.basePath) return [];
|
|
3004
3050
|
this.loadSessionIndex();
|
|
3005
|
-
return this.listRolloutFiles().map((file) => ({
|
|
3051
|
+
return this.listRolloutFiles(options).map((file) => ({
|
|
3006
3052
|
sessionId: extractSessionId(file),
|
|
3007
3053
|
sourcePath: file,
|
|
3008
3054
|
fingerprint: this.sourceFingerprint(file)
|
|
@@ -3020,7 +3066,6 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3020
3066
|
const meta = this.sessionMetaMap.get(sessionId);
|
|
3021
3067
|
if (!meta) throw new Error(`Session not found: ${sessionId}`);
|
|
3022
3068
|
if (!existsSync7(meta.sourcePath)) throw new Error(`Session file missing: ${meta.sourcePath}`);
|
|
3023
|
-
const content = readFileSync5(meta.sourcePath, "utf-8");
|
|
3024
3069
|
const messages = [];
|
|
3025
3070
|
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
3026
3071
|
let totalInputTokens = 0;
|
|
@@ -3036,7 +3081,7 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3036
3081
|
let prevOutput = 0;
|
|
3037
3082
|
let prevReasoning = 0;
|
|
3038
3083
|
let prevCachedInput = 0;
|
|
3039
|
-
for (const record of
|
|
3084
|
+
for (const record of readJsonlFile(meta.sourcePath)) {
|
|
3040
3085
|
try {
|
|
3041
3086
|
const recordType = String(record["type"] ?? "");
|
|
3042
3087
|
if (recordType === "turn_context") {
|
|
@@ -3224,7 +3269,7 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3224
3269
|
this.sessionIndexMtime = mtime;
|
|
3225
3270
|
if (mtime === null) return;
|
|
3226
3271
|
try {
|
|
3227
|
-
const content =
|
|
3272
|
+
const content = readFileSync4(indexPath, "utf-8");
|
|
3228
3273
|
for (const record of parseJsonlLines(content)) {
|
|
3229
3274
|
const sid = String(record["id"] ?? "").trim();
|
|
3230
3275
|
const threadName = String(record["thread_name"] ?? "").trim();
|
|
@@ -3241,13 +3286,13 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3241
3286
|
}
|
|
3242
3287
|
// ---- Session head parsing ----
|
|
3243
3288
|
readFilePrefix(filePath, bytes = 64 * 1024) {
|
|
3244
|
-
const fd =
|
|
3289
|
+
const fd = openSync2(filePath, "r");
|
|
3245
3290
|
try {
|
|
3246
3291
|
const buffer = Buffer.alloc(bytes);
|
|
3247
|
-
const bytesRead =
|
|
3292
|
+
const bytesRead = readSync2(fd, buffer, 0, bytes, 0);
|
|
3248
3293
|
return buffer.subarray(0, bytesRead).toString("utf-8");
|
|
3249
3294
|
} finally {
|
|
3250
|
-
|
|
3295
|
+
closeSync2(fd);
|
|
3251
3296
|
}
|
|
3252
3297
|
}
|
|
3253
3298
|
parseSessionHead(filePath, options) {
|
|
@@ -3257,23 +3302,12 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3257
3302
|
if (options?.fast) {
|
|
3258
3303
|
return this.parseFastSessionHeadResult(filePath);
|
|
3259
3304
|
}
|
|
3260
|
-
const content = readFileSync5(filePath, "utf-8");
|
|
3261
|
-
const lines = content.split("\n").filter((l) => l.trim());
|
|
3262
|
-
if (lines.length === 0) return skippedSession("empty file");
|
|
3263
3305
|
const sessionId = extractSessionId(filePath);
|
|
3264
|
-
let
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
}
|
|
3270
|
-
const payload = firstRecord["payload"] ?? {};
|
|
3271
|
-
const createdAt = parseTimestampMs2(firstRecord) || parseTimestampMs2(payload) || statSync4(filePath).mtimeMs;
|
|
3272
|
-
const indexTitle = this.getTitleForSession(sessionId);
|
|
3273
|
-
const messageTitle = this.extractTitleFromLines(lines);
|
|
3274
|
-
const directoryTitle = basenameTitle(payload["cwd"] ? String(payload["cwd"]) : null);
|
|
3275
|
-
const title = resolveSessionTitle(indexTitle, messageTitle, directoryTitle);
|
|
3276
|
-
let updatedAt = createdAt;
|
|
3306
|
+
let firstPayload = {};
|
|
3307
|
+
let createdAt = 0;
|
|
3308
|
+
let lineCount = 0;
|
|
3309
|
+
const titleLines = [];
|
|
3310
|
+
let updatedAt = 0;
|
|
3277
3311
|
let messageCount = 0;
|
|
3278
3312
|
let model = null;
|
|
3279
3313
|
let activeModel = null;
|
|
@@ -3289,18 +3323,31 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3289
3323
|
let scanPrevCachedInput = 0;
|
|
3290
3324
|
const COUNTED_TYPES = /* @__PURE__ */ new Set(["message", "function_call", "function_call_output"]);
|
|
3291
3325
|
let hasNonInternalRecord = false;
|
|
3292
|
-
for (const line of
|
|
3326
|
+
for (const line of readJsonlFileLines(filePath)) {
|
|
3327
|
+
lineCount += 1;
|
|
3328
|
+
if (lineCount === 1) {
|
|
3329
|
+
let firstRecord;
|
|
3330
|
+
try {
|
|
3331
|
+
firstRecord = JSON.parse(line);
|
|
3332
|
+
} catch {
|
|
3333
|
+
return skippedSession("malformed first record");
|
|
3334
|
+
}
|
|
3335
|
+
firstPayload = firstRecord["payload"] ?? {};
|
|
3336
|
+
createdAt = parseTimestampMs2(firstRecord) || parseTimestampMs2(firstPayload) || statSync4(filePath).mtimeMs;
|
|
3337
|
+
updatedAt = createdAt;
|
|
3338
|
+
}
|
|
3339
|
+
if (titleLines.length < 20) titleLines.push(line);
|
|
3293
3340
|
try {
|
|
3294
3341
|
const data = JSON.parse(line);
|
|
3295
3342
|
const recordType = String(data["type"] ?? "");
|
|
3296
|
-
const
|
|
3297
|
-
const payloadType = String(
|
|
3343
|
+
const payload = data["payload"] ?? {};
|
|
3344
|
+
const payloadType = String(payload["type"] ?? "");
|
|
3298
3345
|
if (isInternalEventType2(recordType) || isInternalEventType2(payloadType)) continue;
|
|
3299
3346
|
hasNonInternalRecord = true;
|
|
3300
3347
|
const recordTs = parseTimestampMs2(data) || parseTimestampMs2(data["payload"] ?? {});
|
|
3301
3348
|
if (recordTs > updatedAt) updatedAt = recordTs;
|
|
3302
3349
|
if (recordType === "session_meta" || recordType === "turn_context") {
|
|
3303
|
-
const nextModel = extractModelName(
|
|
3350
|
+
const nextModel = extractModelName(payload["model"]);
|
|
3304
3351
|
if (nextModel) {
|
|
3305
3352
|
activeModel = nextModel;
|
|
3306
3353
|
model ??= nextModel;
|
|
@@ -3308,7 +3355,7 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3308
3355
|
continue;
|
|
3309
3356
|
}
|
|
3310
3357
|
if (recordType === "response_item") {
|
|
3311
|
-
const p =
|
|
3358
|
+
const p = payload;
|
|
3312
3359
|
const pType = String(p["type"] ?? "");
|
|
3313
3360
|
if (COUNTED_TYPES.has(pType)) {
|
|
3314
3361
|
messageCount++;
|
|
@@ -3370,8 +3417,12 @@ var CodexAgent = class extends FileSystemSessionSource {
|
|
|
3370
3417
|
} catch {
|
|
3371
3418
|
}
|
|
3372
3419
|
}
|
|
3420
|
+
if (lineCount === 0) return skippedSession("empty file");
|
|
3373
3421
|
if (!hasNonInternalRecord) return filteredSession("internal events only");
|
|
3374
|
-
const
|
|
3422
|
+
const indexTitle = this.getTitleForSession(sessionId);
|
|
3423
|
+
const messageTitle = this.extractTitleFromLines(titleLines);
|
|
3424
|
+
const directory = firstPayload["cwd"] ? String(firstPayload["cwd"]) : "";
|
|
3425
|
+
const title = resolveSessionTitle(indexTitle, messageTitle, basenameTitle(directory || null));
|
|
3375
3426
|
return parsedSession({
|
|
3376
3427
|
id: sessionId,
|
|
3377
3428
|
slug: `codex/${sessionId}`,
|
|
@@ -4003,7 +4054,7 @@ var CursorAgent = class extends DatabaseSessionSource {
|
|
|
4003
4054
|
if (!existsSync8(wsJsonPath)) continue;
|
|
4004
4055
|
let workspacePath;
|
|
4005
4056
|
try {
|
|
4006
|
-
const data = JSON.parse(
|
|
4057
|
+
const data = JSON.parse(readFileSync5(wsJsonPath, "utf-8"));
|
|
4007
4058
|
const uri = data.folder ?? data.workspace ?? "";
|
|
4008
4059
|
if (!uri) continue;
|
|
4009
4060
|
workspacePath = normalize(decodeURIComponent(uri.replace(/^file:\/\//, "")));
|
|
@@ -4606,9 +4657,9 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4606
4657
|
perf.end(scanMarker);
|
|
4607
4658
|
return heads;
|
|
4608
4659
|
}
|
|
4609
|
-
listSessionSources() {
|
|
4660
|
+
listSessionSources(options) {
|
|
4610
4661
|
if (!this.basePath) return [];
|
|
4611
|
-
return this.listSessionFiles().map((file) => ({
|
|
4662
|
+
return this.listSessionFiles(options).map((file) => ({
|
|
4612
4663
|
sessionId: extractSessionIdFromFilename(file),
|
|
4613
4664
|
sourcePath: file,
|
|
4614
4665
|
fingerprint: this.sourceFingerprint(file)
|
|
@@ -4713,7 +4764,7 @@ var PiAgent = class extends FileSystemSessionSource {
|
|
|
4713
4764
|
});
|
|
4714
4765
|
}
|
|
4715
4766
|
parsePiFile(filePath) {
|
|
4716
|
-
const records = Array.from(parseJsonlLines(
|
|
4767
|
+
const records = Array.from(parseJsonlLines(readFileSync6(filePath, "utf-8")));
|
|
4717
4768
|
if (records.length === 0) throw new Error("empty file");
|
|
4718
4769
|
const header = records.find((record) => record["type"] === "session");
|
|
4719
4770
|
if (!header) throw new Error("missing session header");
|
|
@@ -5078,7 +5129,7 @@ var realFs = {
|
|
|
5078
5129
|
},
|
|
5079
5130
|
readText(path2) {
|
|
5080
5131
|
try {
|
|
5081
|
-
return
|
|
5132
|
+
return readFileSync7(path2, "utf8");
|
|
5082
5133
|
} catch {
|
|
5083
5134
|
return null;
|
|
5084
5135
|
}
|
|
@@ -5091,43 +5142,6 @@ var realFs = {
|
|
|
5091
5142
|
};
|
|
5092
5143
|
}
|
|
5093
5144
|
};
|
|
5094
|
-
function getAgentName(session) {
|
|
5095
|
-
return session.slug.split("/")[0]?.toLowerCase() || "unknown";
|
|
5096
|
-
}
|
|
5097
|
-
function buildProjectGroups(sessions) {
|
|
5098
|
-
const groups = /* @__PURE__ */ new Map();
|
|
5099
|
-
for (const session of sessions) {
|
|
5100
|
-
const identity = session.project_identity;
|
|
5101
|
-
if (!identity) continue;
|
|
5102
|
-
const activity = session.time_updated ?? session.time_created;
|
|
5103
|
-
const groupKey = `${identity.kind}:${identity.key}`;
|
|
5104
|
-
const current = groups.get(groupKey);
|
|
5105
|
-
if (current) {
|
|
5106
|
-
current.sources.add(getAgentName(session));
|
|
5107
|
-
current.sessionCount += 1;
|
|
5108
|
-
current.lastActivity = Math.max(current.lastActivity, activity);
|
|
5109
|
-
} else {
|
|
5110
|
-
groups.set(groupKey, {
|
|
5111
|
-
identity,
|
|
5112
|
-
sources: /* @__PURE__ */ new Set([getAgentName(session)]),
|
|
5113
|
-
sessionCount: 1,
|
|
5114
|
-
lastActivity: activity
|
|
5115
|
-
});
|
|
5116
|
-
}
|
|
5117
|
-
}
|
|
5118
|
-
return [...groups.values()].map((group) => ({
|
|
5119
|
-
identityKind: group.identity.kind,
|
|
5120
|
-
identityKey: group.identity.key,
|
|
5121
|
-
displayName: group.identity.displayName,
|
|
5122
|
-
sources: [...group.sources].sort(),
|
|
5123
|
-
sessionCount: group.sessionCount,
|
|
5124
|
-
lastActivity: group.lastActivity || null
|
|
5125
|
-
})).sort((a, b) => {
|
|
5126
|
-
if (a.identityKind === "loose" && b.identityKind !== "loose") return 1;
|
|
5127
|
-
if (b.identityKind === "loose" && a.identityKind !== "loose") return -1;
|
|
5128
|
-
return (b.lastActivity ?? 0) - (a.lastActivity ?? 0);
|
|
5129
|
-
});
|
|
5130
|
-
}
|
|
5131
5145
|
var MANIFESTS = [
|
|
5132
5146
|
"package.json",
|
|
5133
5147
|
"Cargo.toml",
|
|
@@ -5140,6 +5154,23 @@ var MANIFESTS = [
|
|
|
5140
5154
|
var PARSEABLE_MANIFESTS = ["package.json", "Cargo.toml", "pyproject.toml"];
|
|
5141
5155
|
var LOOSE_DIRS = /* @__PURE__ */ new Set(["/tmp", "/private/tmp"]);
|
|
5142
5156
|
var LOOSE_HOME_DIRS = ["Desktop", "Downloads", "Documents"];
|
|
5157
|
+
var PROJECT_IDENTITY_KINDS = /* @__PURE__ */ new Set([
|
|
5158
|
+
"git_remote",
|
|
5159
|
+
"git_common_dir",
|
|
5160
|
+
"manifest_path",
|
|
5161
|
+
"synthetic",
|
|
5162
|
+
"path",
|
|
5163
|
+
"loose"
|
|
5164
|
+
]);
|
|
5165
|
+
function isProjectIdentityKind(value) {
|
|
5166
|
+
return PROJECT_IDENTITY_KINDS.has(value);
|
|
5167
|
+
}
|
|
5168
|
+
function getProjectIdentityKey(identity) {
|
|
5169
|
+
return `${identity.kind}:${identity.key}`;
|
|
5170
|
+
}
|
|
5171
|
+
function matchesProjectIdentity(identity, expected) {
|
|
5172
|
+
return identity?.kind === expected.kind && identity.key === expected.key;
|
|
5173
|
+
}
|
|
5143
5174
|
function normalizeGitRemote(url) {
|
|
5144
5175
|
if (!url) return null;
|
|
5145
5176
|
let value = url.trim().replace(/\.git$/, "");
|
|
@@ -5270,15 +5301,53 @@ function parseManifestName(file, text) {
|
|
|
5270
5301
|
}
|
|
5271
5302
|
return null;
|
|
5272
5303
|
}
|
|
5304
|
+
function getAgentName(session) {
|
|
5305
|
+
return session.slug.split("/")[0]?.toLowerCase() || "unknown";
|
|
5306
|
+
}
|
|
5307
|
+
function buildProjectGroups(sessions) {
|
|
5308
|
+
const groups = /* @__PURE__ */ new Map();
|
|
5309
|
+
for (const session of sessions) {
|
|
5310
|
+
const identity = session.project_identity;
|
|
5311
|
+
if (!identity) continue;
|
|
5312
|
+
const activity = session.time_updated ?? session.time_created;
|
|
5313
|
+
const groupKey = getProjectIdentityKey(identity);
|
|
5314
|
+
const current = groups.get(groupKey);
|
|
5315
|
+
if (current) {
|
|
5316
|
+
current.sources.add(getAgentName(session));
|
|
5317
|
+
current.sessionCount += 1;
|
|
5318
|
+
current.lastActivity = Math.max(current.lastActivity, activity);
|
|
5319
|
+
} else {
|
|
5320
|
+
groups.set(groupKey, {
|
|
5321
|
+
identity,
|
|
5322
|
+
sources: /* @__PURE__ */ new Set([getAgentName(session)]),
|
|
5323
|
+
sessionCount: 1,
|
|
5324
|
+
lastActivity: activity
|
|
5325
|
+
});
|
|
5326
|
+
}
|
|
5327
|
+
}
|
|
5328
|
+
return [...groups.values()].map((group) => ({
|
|
5329
|
+
identityKind: group.identity.kind,
|
|
5330
|
+
identityKey: group.identity.key,
|
|
5331
|
+
displayName: group.identity.displayName,
|
|
5332
|
+
sources: [...group.sources].sort(),
|
|
5333
|
+
sessionCount: group.sessionCount,
|
|
5334
|
+
lastActivity: group.lastActivity || null
|
|
5335
|
+
})).sort((a, b) => {
|
|
5336
|
+
if (a.identityKind === "loose" && b.identityKind !== "loose") return 1;
|
|
5337
|
+
if (b.identityKind === "loose" && a.identityKind !== "loose") return -1;
|
|
5338
|
+
return (b.lastActivity ?? 0) - (a.lastActivity ?? 0);
|
|
5339
|
+
});
|
|
5340
|
+
}
|
|
5273
5341
|
function createProjectScopeMatcher(queryPath, fs = realFs) {
|
|
5342
|
+
const identity = computeIdentity(queryPath, fs);
|
|
5274
5343
|
return {
|
|
5275
|
-
|
|
5344
|
+
identity: { kind: identity.kind, key: identity.key },
|
|
5276
5345
|
path: normalizeScopePath(queryPath)
|
|
5277
5346
|
};
|
|
5278
5347
|
}
|
|
5279
5348
|
function matchesProjectScope(session, scope) {
|
|
5280
5349
|
if (!session.directory) return false;
|
|
5281
|
-
if (session.project_identity
|
|
5350
|
+
if (matchesProjectIdentity(session.project_identity, scope.identity)) return true;
|
|
5282
5351
|
return isPathScopeMatch(scope.path, session.directory);
|
|
5283
5352
|
}
|
|
5284
5353
|
function filterSessionsByProjectScope(sessions, queryPath, fs) {
|
|
@@ -5571,6 +5640,13 @@ function getFtsIntegrityCheckedPath() {
|
|
|
5571
5640
|
function setFtsIntegrityCheckedPath(path2) {
|
|
5572
5641
|
ftsIntegrityCheckedPath = path2;
|
|
5573
5642
|
}
|
|
5643
|
+
var schemaEnsuredPath = null;
|
|
5644
|
+
function getSchemaEnsuredPath() {
|
|
5645
|
+
return schemaEnsuredPath;
|
|
5646
|
+
}
|
|
5647
|
+
function setSchemaEnsuredPath(path2) {
|
|
5648
|
+
schemaEnsuredPath = path2;
|
|
5649
|
+
}
|
|
5574
5650
|
function getCacheDir2() {
|
|
5575
5651
|
return join11(homedir4(), ".cache", "codesesh");
|
|
5576
5652
|
}
|
|
@@ -6033,7 +6109,10 @@ function withCacheDb(fn) {
|
|
|
6033
6109
|
const db = openDb(cachePath);
|
|
6034
6110
|
if (!db) return null;
|
|
6035
6111
|
try {
|
|
6036
|
-
|
|
6112
|
+
if (getSchemaEnsuredPath() !== cachePath) {
|
|
6113
|
+
ensureSchema(db, cachePath);
|
|
6114
|
+
setSchemaEnsuredPath(cachePath);
|
|
6115
|
+
}
|
|
6037
6116
|
return fn(db);
|
|
6038
6117
|
} catch {
|
|
6039
6118
|
return null;
|
|
@@ -6877,30 +6956,6 @@ function ensureSchema(db, dbPath) {
|
|
|
6877
6956
|
setCacheSchemaVersion(db);
|
|
6878
6957
|
}
|
|
6879
6958
|
}
|
|
6880
|
-
function shouldBulkSyncSearchIndex(options, changedCount) {
|
|
6881
|
-
if (options.isBulk != null) {
|
|
6882
|
-
return options.isBulk;
|
|
6883
|
-
}
|
|
6884
|
-
const threshold = options.bulkThreshold ?? SEARCH_INDEX_BULK_SYNC_THRESHOLD;
|
|
6885
|
-
return threshold > 0 && changedCount >= threshold;
|
|
6886
|
-
}
|
|
6887
|
-
function sessionContentHash(session) {
|
|
6888
|
-
return JSON.stringify([
|
|
6889
|
-
session.slug,
|
|
6890
|
-
session.title,
|
|
6891
|
-
session.directory,
|
|
6892
|
-
session.time_created,
|
|
6893
|
-
session.time_updated ?? session.time_created,
|
|
6894
|
-
session.stats.message_count,
|
|
6895
|
-
session.stats.total_input_tokens,
|
|
6896
|
-
session.stats.total_output_tokens,
|
|
6897
|
-
session.stats.total_cache_read_tokens ?? 0,
|
|
6898
|
-
session.stats.total_cache_create_tokens ?? 0,
|
|
6899
|
-
session.stats.total_cost,
|
|
6900
|
-
session.stats.cost_source ?? "",
|
|
6901
|
-
session.stats.total_tokens ?? 0
|
|
6902
|
-
]);
|
|
6903
|
-
}
|
|
6904
6959
|
function escapeFtsTerm(value) {
|
|
6905
6960
|
return value.replaceAll('"', '""');
|
|
6906
6961
|
}
|
|
@@ -6923,9 +6978,7 @@ function splitSearchTokens(input) {
|
|
|
6923
6978
|
}
|
|
6924
6979
|
token += char;
|
|
6925
6980
|
}
|
|
6926
|
-
if (token)
|
|
6927
|
-
tokens.push(token);
|
|
6928
|
-
}
|
|
6981
|
+
if (token) tokens.push(token);
|
|
6929
6982
|
return tokens;
|
|
6930
6983
|
}
|
|
6931
6984
|
function unwrapSearchValue(value) {
|
|
@@ -6985,7 +7038,10 @@ function parseSearchQuery(input) {
|
|
|
6985
7038
|
if (key === "agent") filters.agent = value.toLowerCase();
|
|
6986
7039
|
else if (key === "project") filters.project = value;
|
|
6987
7040
|
else if (key === "projectkey" || key === "project-key") filters.projectKey = value;
|
|
6988
|
-
else if (key === "
|
|
7041
|
+
else if (key === "projectkind" || key === "project-kind") {
|
|
7042
|
+
if (isProjectIdentityKind(value)) filters.projectKind = value;
|
|
7043
|
+
else consumed = false;
|
|
7044
|
+
} else if (key === "cwd") filters.cwd = value;
|
|
6989
7045
|
else if (key === "tool") filters.tools = appendUnique(filters.tools, value.toLowerCase());
|
|
6990
7046
|
else if (key === "file" || key === "path") filters.file = value;
|
|
6991
7047
|
else if (key === "kind" || key === "filekind" || key === "file-kind") {
|
|
@@ -6996,21 +7052,15 @@ function parseSearchQuery(input) {
|
|
|
6996
7052
|
}
|
|
6997
7053
|
} else if (key === "tag" || key === "signal") {
|
|
6998
7054
|
const tag = value.toLowerCase();
|
|
6999
|
-
if (isSmartTag(tag))
|
|
7000
|
-
|
|
7001
|
-
} else {
|
|
7002
|
-
consumed = false;
|
|
7003
|
-
}
|
|
7055
|
+
if (isSmartTag(tag)) filters.tags = appendUnique(filters.tags, tag);
|
|
7056
|
+
else consumed = false;
|
|
7004
7057
|
} else if (key === "cost") {
|
|
7005
7058
|
parseCostQualifier(value, filters);
|
|
7006
7059
|
} else {
|
|
7007
7060
|
consumed = false;
|
|
7008
7061
|
}
|
|
7009
|
-
if (consumed)
|
|
7010
|
-
|
|
7011
|
-
} else {
|
|
7012
|
-
textTokens.push(token);
|
|
7013
|
-
}
|
|
7062
|
+
if (consumed) hasQualifiers = true;
|
|
7063
|
+
else textTokens.push(token);
|
|
7014
7064
|
}
|
|
7015
7065
|
return {
|
|
7016
7066
|
text: textTokens.join(" ").trim(),
|
|
@@ -7020,18 +7070,75 @@ function parseSearchQuery(input) {
|
|
|
7020
7070
|
}
|
|
7021
7071
|
function toFtsQuery(input) {
|
|
7022
7072
|
const tokens = splitSearchTokens(input);
|
|
7023
|
-
|
|
7024
|
-
if (/^OR$/i.test(token))
|
|
7025
|
-
return "OR";
|
|
7026
|
-
}
|
|
7073
|
+
return tokens.map((token) => {
|
|
7074
|
+
if (/^OR$/i.test(token)) return "OR";
|
|
7027
7075
|
if (token.startsWith('"') && token.endsWith('"')) {
|
|
7028
7076
|
return `"${escapeFtsTerm(token.slice(1, -1))}"`;
|
|
7029
7077
|
}
|
|
7030
7078
|
return `"${escapeFtsTerm(token)}"`;
|
|
7031
7079
|
}).filter(
|
|
7032
7080
|
(token, index, values) => token !== "OR" || index > 0 && index < values.length - 1 && values[index - 1] !== "OR" && values[index + 1] !== "OR"
|
|
7033
|
-
);
|
|
7034
|
-
|
|
7081
|
+
).join(" ");
|
|
7082
|
+
}
|
|
7083
|
+
var SEARCH_INDEX_STATE_BATCH_SIZE = 900;
|
|
7084
|
+
function shouldBulkSyncSearchIndex(options, changedCount) {
|
|
7085
|
+
if (options.isBulk != null) {
|
|
7086
|
+
return options.isBulk;
|
|
7087
|
+
}
|
|
7088
|
+
const threshold = options.bulkThreshold ?? SEARCH_INDEX_BULK_SYNC_THRESHOLD;
|
|
7089
|
+
return threshold > 0 && changedCount >= threshold;
|
|
7090
|
+
}
|
|
7091
|
+
function sessionContentHash(session) {
|
|
7092
|
+
return JSON.stringify([
|
|
7093
|
+
session.slug,
|
|
7094
|
+
session.title,
|
|
7095
|
+
session.directory,
|
|
7096
|
+
session.time_created,
|
|
7097
|
+
session.time_updated ?? session.time_created,
|
|
7098
|
+
session.stats.message_count,
|
|
7099
|
+
session.stats.total_input_tokens,
|
|
7100
|
+
session.stats.total_output_tokens,
|
|
7101
|
+
session.stats.total_cache_read_tokens ?? 0,
|
|
7102
|
+
session.stats.total_cache_create_tokens ?? 0,
|
|
7103
|
+
session.stats.total_cost,
|
|
7104
|
+
session.stats.cost_source ?? "",
|
|
7105
|
+
session.stats.total_tokens ?? 0
|
|
7106
|
+
]);
|
|
7107
|
+
}
|
|
7108
|
+
function searchIndexStateFromRows(indexedRows, messageCountRows) {
|
|
7109
|
+
return {
|
|
7110
|
+
contentHashBySessionId: new Map(
|
|
7111
|
+
indexedRows.map((row) => [String(row.session_id), String(row.content_hash ?? "")])
|
|
7112
|
+
),
|
|
7113
|
+
messageCountBySessionId: new Map(
|
|
7114
|
+
messageCountRows.map((row) => [String(row.session_id), Number(row.value ?? 0)])
|
|
7115
|
+
)
|
|
7116
|
+
};
|
|
7117
|
+
}
|
|
7118
|
+
function readSearchIndexState(db, agentName, sessionIds) {
|
|
7119
|
+
const rows = [];
|
|
7120
|
+
const uniqueSessionIds = [...new Set(sessionIds)];
|
|
7121
|
+
for (let offset = 0; offset < uniqueSessionIds.length; offset += SEARCH_INDEX_STATE_BATCH_SIZE) {
|
|
7122
|
+
const batch = uniqueSessionIds.slice(offset, offset + SEARCH_INDEX_STATE_BATCH_SIZE);
|
|
7123
|
+
const requestedRows = batch.map(() => "(?)").join(", ");
|
|
7124
|
+
const batchRows = db.prepare(
|
|
7125
|
+
`
|
|
7126
|
+
WITH requested_session_ids(session_id) AS (VALUES ${requestedRows})
|
|
7127
|
+
SELECT
|
|
7128
|
+
requested.session_id,
|
|
7129
|
+
documents.content_hash,
|
|
7130
|
+
COUNT(messages.message_index) AS value
|
|
7131
|
+
FROM requested_session_ids AS requested
|
|
7132
|
+
LEFT JOIN session_documents AS documents
|
|
7133
|
+
ON documents.agent_name = ? AND documents.session_id = requested.session_id
|
|
7134
|
+
LEFT JOIN messages
|
|
7135
|
+
ON messages.agent_name = ? AND messages.session_id = requested.session_id
|
|
7136
|
+
GROUP BY requested.session_id, documents.content_hash
|
|
7137
|
+
`
|
|
7138
|
+
).all(...batch, agentName, agentName);
|
|
7139
|
+
rows.push(...batchRows);
|
|
7140
|
+
}
|
|
7141
|
+
return searchIndexStateFromRows(rows, rows);
|
|
7035
7142
|
}
|
|
7036
7143
|
function loadSearchIndexEntry(agentName, change, loadSessionData) {
|
|
7037
7144
|
try {
|
|
@@ -7207,20 +7314,15 @@ function syncSessionSearchIndex(agentName, sessions, loadSessionData, options =
|
|
|
7207
7314
|
const existingRows = db.prepare(
|
|
7208
7315
|
"SELECT session_id, content_hash FROM session_documents WHERE agent_name = ? ORDER BY id"
|
|
7209
7316
|
).all(agentName);
|
|
7210
|
-
const existingMap = new Map(
|
|
7211
|
-
existingRows.map((row) => [String(row.session_id), String(row.content_hash ?? "")])
|
|
7212
|
-
);
|
|
7213
7317
|
const sessionSortIndexMap = new Map(sessions.map((session, index) => [session.id, index]));
|
|
7214
7318
|
const messageCountRows = db.prepare(
|
|
7215
7319
|
"SELECT session_id, COUNT(*) AS value FROM messages WHERE agent_name = ? GROUP BY session_id"
|
|
7216
7320
|
).all(agentName);
|
|
7217
|
-
const
|
|
7218
|
-
messageCountRows.map((row) => [String(row.session_id), Number(row.value ?? 0)])
|
|
7219
|
-
);
|
|
7321
|
+
const searchIndexState = searchIndexStateFromRows(existingRows, messageCountRows);
|
|
7220
7322
|
const sessionMap = new Map(sessions.map((session) => [session.id, session]));
|
|
7221
7323
|
const toDelete = existingRows.map((row) => String(row.session_id)).filter((sessionId) => !sessionMap.has(sessionId));
|
|
7222
7324
|
const toUpsert = sessions.filter(
|
|
7223
|
-
(session) =>
|
|
7325
|
+
(session) => searchIndexState.contentHashBySessionId.get(session.id) !== sessionContentHash(session) || searchIndexState.messageCountBySessionId.get(session.id) !== session.stats.message_count
|
|
7224
7326
|
);
|
|
7225
7327
|
const changedCount = toDelete.length + toUpsert.length;
|
|
7226
7328
|
const isBulk = shouldBulkSyncSearchIndex(options, changedCount);
|
|
@@ -7278,17 +7380,14 @@ function syncSessionSearchIndexChanges(agentName, changes, removedSessionIds, lo
|
|
|
7278
7380
|
return withCacheDb((db) => {
|
|
7279
7381
|
ensureFtsConsistency(db);
|
|
7280
7382
|
const startedAt = performance.now();
|
|
7281
|
-
const
|
|
7282
|
-
|
|
7383
|
+
const searchIndexState = readSearchIndexState(
|
|
7384
|
+
db,
|
|
7385
|
+
agentName,
|
|
7386
|
+
changes.map(({ session }) => session.id)
|
|
7283
7387
|
);
|
|
7284
|
-
const
|
|
7285
|
-
|
|
7388
|
+
const toUpsert = changes.filter(
|
|
7389
|
+
({ session }) => (searchIndexState.contentHashBySessionId.get(session.id) ?? "") !== sessionContentHash(session) || (searchIndexState.messageCountBySessionId.get(session.id) ?? 0) !== session.stats.message_count
|
|
7286
7390
|
);
|
|
7287
|
-
const toUpsert = changes.filter(({ session }) => {
|
|
7288
|
-
const indexed = getIndexedRow.get(agentName, session.id);
|
|
7289
|
-
const messageCount = getMessageCount.get(agentName, session.id);
|
|
7290
|
-
return String(indexed?.content_hash ?? "") !== sessionContentHash(session) || Number(messageCount?.value ?? 0) !== session.stats.message_count;
|
|
7291
|
-
});
|
|
7292
7391
|
const uniqueRemovedSessionIds = Array.from(new Set(removedSessionIds));
|
|
7293
7392
|
const changedCount = uniqueRemovedSessionIds.length + toUpsert.length;
|
|
7294
7393
|
const isBulk = shouldBulkSyncSearchIndex(options, changedCount);
|
|
@@ -7339,6 +7438,7 @@ function mergeSearchQueryOptions(query, options) {
|
|
|
7339
7438
|
...options,
|
|
7340
7439
|
agent: options.agent ?? parsed2.filters.agent,
|
|
7341
7440
|
project: options.project ?? parsed2.filters.project,
|
|
7441
|
+
projectKind: options.projectKind ?? parsed2.filters.projectKind,
|
|
7342
7442
|
projectKey: options.projectKey ?? parsed2.filters.projectKey,
|
|
7343
7443
|
cwd: options.cwd ?? parsed2.filters.cwd,
|
|
7344
7444
|
tags: mergeSearchLists(options.tags, parsed2.filters.tags),
|
|
@@ -7374,13 +7474,20 @@ function buildSessionSearchFilters(options) {
|
|
|
7374
7474
|
clauses.push("s.agent_name = ?");
|
|
7375
7475
|
params.push(options.agent);
|
|
7376
7476
|
}
|
|
7377
|
-
if (options.projectKey) {
|
|
7378
|
-
|
|
7379
|
-
|
|
7477
|
+
if (options.projectKind || options.projectKey) {
|
|
7478
|
+
if (options.projectKind && options.projectKey) {
|
|
7479
|
+
clauses.push("s.project_identity_kind = ? AND s.project_identity_key = ?");
|
|
7480
|
+
params.push(options.projectKind, options.projectKey);
|
|
7481
|
+
} else {
|
|
7482
|
+
clauses.push("0");
|
|
7483
|
+
}
|
|
7380
7484
|
}
|
|
7381
7485
|
if (options.cwd) {
|
|
7382
|
-
|
|
7383
|
-
|
|
7486
|
+
const identity = computeIdentity(options.cwd, realFs);
|
|
7487
|
+
clauses.push(
|
|
7488
|
+
"((s.project_identity_kind = ? AND s.project_identity_key = ?) OR LOWER(s.directory) LIKE ? ESCAPE '\\')"
|
|
7489
|
+
);
|
|
7490
|
+
params.push(identity.kind, identity.key, likePattern(options.cwd));
|
|
7384
7491
|
}
|
|
7385
7492
|
if (options.project) {
|
|
7386
7493
|
clauses.push(
|
|
@@ -7625,10 +7732,13 @@ function searchSessions(query, options = {}) {
|
|
|
7625
7732
|
}
|
|
7626
7733
|
function fileActivityFilters(options) {
|
|
7627
7734
|
const path2 = options.path ? normalizeFilePathSearch(options.path) : "";
|
|
7735
|
+
const cwdIdentity = options.cwd ? computeIdentity(options.cwd, realFs) : null;
|
|
7628
7736
|
return {
|
|
7737
|
+
projectKind: options.projectKind ?? null,
|
|
7629
7738
|
projectKey: options.projectKey ?? null,
|
|
7630
7739
|
projectLike: options.project ? likePattern(options.project) : null,
|
|
7631
|
-
|
|
7740
|
+
cwdKind: cwdIdentity?.kind ?? null,
|
|
7741
|
+
cwdKey: cwdIdentity?.key ?? null,
|
|
7632
7742
|
cwdLike: options.cwd ? likePattern(options.cwd) : null,
|
|
7633
7743
|
path: path2,
|
|
7634
7744
|
pathLike: path2 ? likePattern(path2) : null
|
|
@@ -7657,9 +7767,13 @@ function buildFileActivityWhere(options) {
|
|
|
7657
7767
|
clauses.push("fa.session_id = ?");
|
|
7658
7768
|
params.push(options.sessionId);
|
|
7659
7769
|
}
|
|
7660
|
-
if (filters.projectKey != null) {
|
|
7661
|
-
|
|
7662
|
-
|
|
7770
|
+
if (filters.projectKind != null || filters.projectKey != null) {
|
|
7771
|
+
if (filters.projectKind != null && filters.projectKey != null) {
|
|
7772
|
+
clauses.push("s.project_identity_kind = ? AND fa.project_identity_key = ?");
|
|
7773
|
+
params.push(filters.projectKind, filters.projectKey);
|
|
7774
|
+
} else {
|
|
7775
|
+
clauses.push("0");
|
|
7776
|
+
}
|
|
7663
7777
|
}
|
|
7664
7778
|
if (filters.projectLike != null) {
|
|
7665
7779
|
clauses.push(
|
|
@@ -7668,8 +7782,10 @@ function buildFileActivityWhere(options) {
|
|
|
7668
7782
|
params.push(filters.projectLike, filters.projectLike, filters.projectLike);
|
|
7669
7783
|
}
|
|
7670
7784
|
if (filters.cwdKey != null) {
|
|
7671
|
-
clauses.push(
|
|
7672
|
-
|
|
7785
|
+
clauses.push(
|
|
7786
|
+
"((s.project_identity_kind = ? AND s.project_identity_key = ?) OR LOWER(s.directory) LIKE ? ESCAPE '\\')"
|
|
7787
|
+
);
|
|
7788
|
+
params.push(filters.cwdKind, filters.cwdKey, filters.cwdLike);
|
|
7673
7789
|
}
|
|
7674
7790
|
if (filters.pathLike != null) {
|
|
7675
7791
|
const pathQuery = filePathFtsQuery(filters.path);
|
|
@@ -7767,6 +7883,7 @@ function searchFileActivitySessions(query, options = {}) {
|
|
|
7767
7883
|
if (!path2) return [];
|
|
7768
7884
|
const rows = listFileActivity({
|
|
7769
7885
|
agent: search.options.agent,
|
|
7886
|
+
projectKind: search.options.projectKind,
|
|
7770
7887
|
projectKey: search.options.projectKey,
|
|
7771
7888
|
project: search.options.project,
|
|
7772
7889
|
cwd: search.options.cwd,
|
|
@@ -7875,16 +7992,41 @@ function isAgentCacheInitialized(agentName, indexVersion = CACHE_INITIALIZATION_
|
|
|
7875
7992
|
}
|
|
7876
7993
|
function markAgentCacheInitialized(agentName, indexVersion = CACHE_INITIALIZATION_VERSION) {
|
|
7877
7994
|
withCacheDb((db) => {
|
|
7878
|
-
const now = Date.now();
|
|
7879
7995
|
db.prepare(
|
|
7880
7996
|
`
|
|
7881
7997
|
INSERT INTO cache_initialization(agent_name, initialized_at, index_version, last_sync_at)
|
|
7882
|
-
VALUES (?, ?, ?,
|
|
7998
|
+
VALUES (?, ?, ?, 0)
|
|
7883
7999
|
ON CONFLICT(agent_name) DO UPDATE SET
|
|
7884
|
-
index_version = excluded.index_version
|
|
7885
|
-
last_sync_at = excluded.last_sync_at
|
|
8000
|
+
index_version = excluded.index_version
|
|
7886
8001
|
`
|
|
7887
|
-
).run(agentName, now, indexVersion
|
|
8002
|
+
).run(agentName, Date.now(), indexVersion);
|
|
8003
|
+
});
|
|
8004
|
+
}
|
|
8005
|
+
function getAgentLastFullSyncAt(agentName) {
|
|
8006
|
+
if (!hasCacheStorage()) {
|
|
8007
|
+
return null;
|
|
8008
|
+
}
|
|
8009
|
+
return withCacheDbReadOnly((db) => {
|
|
8010
|
+
if (!tableExists(db, "cache_initialization")) return null;
|
|
8011
|
+
const row = db.prepare(
|
|
8012
|
+
`
|
|
8013
|
+
SELECT last_sync_at
|
|
8014
|
+
FROM cache_initialization
|
|
8015
|
+
WHERE agent_name = ?
|
|
8016
|
+
`
|
|
8017
|
+
).get(agentName);
|
|
8018
|
+
return row?.last_sync_at || null;
|
|
8019
|
+
}) ?? null;
|
|
8020
|
+
}
|
|
8021
|
+
function markAgentFullSyncCompleted(agentName) {
|
|
8022
|
+
withCacheDb((db) => {
|
|
8023
|
+
db.prepare(
|
|
8024
|
+
`
|
|
8025
|
+
UPDATE cache_initialization
|
|
8026
|
+
SET last_sync_at = ?
|
|
8027
|
+
WHERE agent_name = ?
|
|
8028
|
+
`
|
|
8029
|
+
).run(Date.now(), agentName);
|
|
7888
8030
|
});
|
|
7889
8031
|
}
|
|
7890
8032
|
function loadCachedSessionData(agentName, sessionId) {
|
|
@@ -8101,6 +8243,7 @@ function saveCachedSessionChanges(agentName, changes, removedSessionIds, meta =
|
|
|
8101
8243
|
}
|
|
8102
8244
|
function clearCache() {
|
|
8103
8245
|
setFtsIntegrityCheckedPath(null);
|
|
8246
|
+
setSchemaEnsuredPath(null);
|
|
8104
8247
|
if (!hasCacheStorage()) {
|
|
8105
8248
|
deleteLegacyCacheFile();
|
|
8106
8249
|
return;
|
|
@@ -8217,9 +8360,7 @@ function sessionSignature(session) {
|
|
|
8217
8360
|
]);
|
|
8218
8361
|
}
|
|
8219
8362
|
function sortSessions(sessions) {
|
|
8220
|
-
return
|
|
8221
|
-
(a, b) => (b.time_updated ?? b.time_created) - (a.time_updated ?? a.time_created)
|
|
8222
|
-
);
|
|
8363
|
+
return sortSessionsByActivity(sessions);
|
|
8223
8364
|
}
|
|
8224
8365
|
function computeSessionDiff(cachedSessions, updatedSessions, changedIds = [], signature = sessionSignature) {
|
|
8225
8366
|
const cachedMap = new Map(cachedSessions.map((session) => [session.id, session]));
|
|
@@ -8516,6 +8657,7 @@ async function scanAgentFull(agent, options, onProgress, timing = { total: 0 },
|
|
|
8516
8657
|
if (options.writeCache !== false && options.from == null && options.to == null) {
|
|
8517
8658
|
saveCachedSessions(agent.name, tagged.sessions, meta);
|
|
8518
8659
|
markAgentCacheInitialized(agent.name);
|
|
8660
|
+
markAgentFullSyncCompleted(agent.name);
|
|
8519
8661
|
}
|
|
8520
8662
|
onProgress?.({ agent: agent.name, phase: "complete", newCount: tagged.sessions.length });
|
|
8521
8663
|
const filtered2 = filterSessions(tagged.sessions, options);
|
|
@@ -8932,10 +9074,11 @@ function buildDashboard(sessions, options) {
|
|
|
8932
9074
|
for (const session of sessions) {
|
|
8933
9075
|
const agentName = getSessionAgentName(session);
|
|
8934
9076
|
if (scope.agent && agentName !== scope.agent) continue;
|
|
8935
|
-
if (scope.projectKey) {
|
|
9077
|
+
if (scope.projectKind || scope.projectKey) {
|
|
8936
9078
|
const identity = session.project_identity;
|
|
8937
|
-
if (!identity || identity.key !== scope.projectKey)
|
|
8938
|
-
|
|
9079
|
+
if (!identity || !scope.projectKind || !scope.projectKey || identity.kind !== scope.projectKind || identity.key !== scope.projectKey) {
|
|
9080
|
+
continue;
|
|
9081
|
+
}
|
|
8939
9082
|
}
|
|
8940
9083
|
const activity = getSessionActivityTime(session);
|
|
8941
9084
|
if (from != null && activity < from) continue;
|
|
@@ -9034,6 +9177,90 @@ function buildDashboard(sessions, options) {
|
|
|
9034
9177
|
recentSessions
|
|
9035
9178
|
};
|
|
9036
9179
|
}
|
|
9180
|
+
function executeSessionSearch(query, options, snapshot) {
|
|
9181
|
+
const merged = mergeSearchQueryOptions(query, options);
|
|
9182
|
+
if (!needsIndexedSearch(merged.text, merged.options)) {
|
|
9183
|
+
return searchRecentSessions(snapshot, merged.options);
|
|
9184
|
+
}
|
|
9185
|
+
return searchIndexedSessions(query, merged.text, merged.parsed, merged.options);
|
|
9186
|
+
}
|
|
9187
|
+
function needsIndexedSearch(textQuery, options) {
|
|
9188
|
+
return Boolean(textQuery || options.file || options.fileKind || options.tools?.length);
|
|
9189
|
+
}
|
|
9190
|
+
function filterSessionsByActivityWindow(sessions, from, to) {
|
|
9191
|
+
if (from == null && to == null) return sessions;
|
|
9192
|
+
return sessions.filter((session) => {
|
|
9193
|
+
const activity = getSessionActivityTime(session);
|
|
9194
|
+
if (from != null && activity < from) return false;
|
|
9195
|
+
if (to != null && activity > to) return false;
|
|
9196
|
+
return true;
|
|
9197
|
+
});
|
|
9198
|
+
}
|
|
9199
|
+
function matchesRecentSearchFilters(session, options, projectScope) {
|
|
9200
|
+
if (options.projectKind || options.projectKey) {
|
|
9201
|
+
if (!options.projectKind || !options.projectKey || !matchesProjectIdentity(session.project_identity, {
|
|
9202
|
+
kind: options.projectKind,
|
|
9203
|
+
key: options.projectKey
|
|
9204
|
+
})) {
|
|
9205
|
+
return false;
|
|
9206
|
+
}
|
|
9207
|
+
}
|
|
9208
|
+
if (projectScope && !matchesProjectScope(session, projectScope)) return false;
|
|
9209
|
+
if (options.project) {
|
|
9210
|
+
const projectNeedle = options.project.toLowerCase();
|
|
9211
|
+
const projectText = [
|
|
9212
|
+
session.project_identity?.key,
|
|
9213
|
+
session.project_identity?.displayName,
|
|
9214
|
+
session.directory
|
|
9215
|
+
].filter(Boolean).join("\n").toLowerCase();
|
|
9216
|
+
if (!projectText.includes(projectNeedle)) return false;
|
|
9217
|
+
}
|
|
9218
|
+
if (options.tags?.length && !options.tags.every((tag) => session.smart_tags?.includes(tag))) {
|
|
9219
|
+
return false;
|
|
9220
|
+
}
|
|
9221
|
+
if (!sessionMatchesSearchCost(session, options)) return false;
|
|
9222
|
+
return true;
|
|
9223
|
+
}
|
|
9224
|
+
function searchRecentSessions(snapshot, options) {
|
|
9225
|
+
const projectScope = options.cwd ? createProjectScopeMatcher(options.cwd) : null;
|
|
9226
|
+
const entries = options.agent ? [[options.agent, snapshot.byAgent[options.agent] ?? []]] : Object.entries(snapshot.byAgent);
|
|
9227
|
+
return entries.flatMap(
|
|
9228
|
+
([agentName, sessions]) => filterSessionsByActivityWindow(sessions, options.from, options.to).filter((session) => matchesRecentSearchFilters(session, options, projectScope)).map((session) => ({ agentName, session }))
|
|
9229
|
+
).sort(
|
|
9230
|
+
(a, b) => (b.session.time_updated ?? b.session.time_created) - (a.session.time_updated ?? a.session.time_created)
|
|
9231
|
+
).slice(0, options.limit ?? 50).map(({ agentName, session }) => ({
|
|
9232
|
+
agentName,
|
|
9233
|
+
session,
|
|
9234
|
+
snippet: `Recent session \xB7 ${session.directory}`,
|
|
9235
|
+
matchType: "recent"
|
|
9236
|
+
}));
|
|
9237
|
+
}
|
|
9238
|
+
function deriveFileQuery(query, parsed2, options) {
|
|
9239
|
+
return options.file ?? (!parsed2.text ? parsed2.filters.file : void 0) ?? (!parsed2.hasQualifiers && query ? parsed2.text || query : "");
|
|
9240
|
+
}
|
|
9241
|
+
function mergeSearchResultSources(results, limit) {
|
|
9242
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9243
|
+
const merged = [];
|
|
9244
|
+
for (const result of results) {
|
|
9245
|
+
const key = `${result.agentName}/${result.session.id}`;
|
|
9246
|
+
if (seen.has(key)) continue;
|
|
9247
|
+
seen.add(key);
|
|
9248
|
+
merged.push(result);
|
|
9249
|
+
if (merged.length >= limit) break;
|
|
9250
|
+
}
|
|
9251
|
+
return merged;
|
|
9252
|
+
}
|
|
9253
|
+
function canSkipSessionsSearch(fileQuery, textQuery, options) {
|
|
9254
|
+
return Boolean(
|
|
9255
|
+
fileQuery && !textQuery && !options.tools?.length && !options.tags?.length && options.from == null && options.to == null
|
|
9256
|
+
);
|
|
9257
|
+
}
|
|
9258
|
+
function searchIndexedSessions(query, textQuery, parsed2, options) {
|
|
9259
|
+
const fileQuery = deriveFileQuery(query, parsed2, options);
|
|
9260
|
+
const fileResults = fileQuery ? searchFileActivitySessions(fileQuery, options) : [];
|
|
9261
|
+
const sessionResults = canSkipSessionsSearch(fileQuery, textQuery, options) ? [] : searchSessions(query, options);
|
|
9262
|
+
return mergeSearchResultSources([...fileResults, ...sessionResults], options.limit ?? 50);
|
|
9263
|
+
}
|
|
9037
9264
|
|
|
9038
9265
|
export {
|
|
9039
9266
|
registerAgent,
|
|
@@ -9045,6 +9272,7 @@ export {
|
|
|
9045
9272
|
skippedSession,
|
|
9046
9273
|
filteredSession,
|
|
9047
9274
|
getParsedSession,
|
|
9275
|
+
matchesScanWindow,
|
|
9048
9276
|
BaseAgent,
|
|
9049
9277
|
FileSystemSessionSource,
|
|
9050
9278
|
DatabaseSessionSource,
|
|
@@ -9082,9 +9310,12 @@ export {
|
|
|
9082
9310
|
isSqliteAvailable,
|
|
9083
9311
|
fallbackDisplayName,
|
|
9084
9312
|
realFs,
|
|
9085
|
-
|
|
9313
|
+
isProjectIdentityKind,
|
|
9314
|
+
getProjectIdentityKey,
|
|
9315
|
+
matchesProjectIdentity,
|
|
9086
9316
|
normalizeGitRemote,
|
|
9087
9317
|
computeIdentity,
|
|
9318
|
+
buildProjectGroups,
|
|
9088
9319
|
createProjectScopeMatcher,
|
|
9089
9320
|
matchesProjectScope,
|
|
9090
9321
|
filterSessionsByProjectScope,
|
|
@@ -9093,6 +9324,8 @@ export {
|
|
|
9093
9324
|
extractFileActivityOccurrences,
|
|
9094
9325
|
summarizeFileActivity,
|
|
9095
9326
|
extractSessionFileActivity,
|
|
9327
|
+
setFtsIntegrityCheckedPath,
|
|
9328
|
+
getCachePath2,
|
|
9096
9329
|
parseSearchQuery,
|
|
9097
9330
|
syncSessionSearchIndex,
|
|
9098
9331
|
syncSessionSearchIndexChanges,
|
|
@@ -9103,6 +9336,8 @@ export {
|
|
|
9103
9336
|
loadCachedSessions,
|
|
9104
9337
|
isAgentCacheInitialized,
|
|
9105
9338
|
markAgentCacheInitialized,
|
|
9339
|
+
getAgentLastFullSyncAt,
|
|
9340
|
+
markAgentFullSyncCompleted,
|
|
9106
9341
|
loadCachedSessionData,
|
|
9107
9342
|
saveCachedSessions,
|
|
9108
9343
|
saveCachedSessionChanges,
|
|
@@ -9115,6 +9350,7 @@ export {
|
|
|
9115
9350
|
sortSessions,
|
|
9116
9351
|
computeSessionDiff,
|
|
9117
9352
|
filterSessions,
|
|
9353
|
+
ensureSessionTagsSync,
|
|
9118
9354
|
scanSessions,
|
|
9119
9355
|
scanSessionsAsync,
|
|
9120
9356
|
BookmarkStorageUnavailableError,
|
|
@@ -9128,6 +9364,7 @@ export {
|
|
|
9128
9364
|
getSessionActivityTime,
|
|
9129
9365
|
toLocalDateKey,
|
|
9130
9366
|
startOfLocalDay,
|
|
9131
|
-
buildDashboard
|
|
9367
|
+
buildDashboard,
|
|
9368
|
+
executeSessionSearch
|
|
9132
9369
|
};
|
|
9133
|
-
//# sourceMappingURL=chunk-
|
|
9370
|
+
//# sourceMappingURL=chunk-BV65IEWZ.js.map
|