conare 0.5.12 → 0.5.14
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/index.js +118 -20
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1791,6 +1791,9 @@ __export(exports_interactive, {
|
|
|
1791
1791
|
spinner: () => Y2,
|
|
1792
1792
|
showLocalChatsCounted: () => showLocalChatsCounted,
|
|
1793
1793
|
showDetectedApps: () => showDetectedApps,
|
|
1794
|
+
showCountingToolProgress: () => showCountingToolProgress,
|
|
1795
|
+
showCountingToolDone: () => showCountingToolDone,
|
|
1796
|
+
showCountingToolChats: () => showCountingToolChats,
|
|
1794
1797
|
showCountingLocalChats: () => showCountingLocalChats,
|
|
1795
1798
|
selectMcpTargets: () => selectMcpTargets,
|
|
1796
1799
|
selectChatSources: () => selectChatSources,
|
|
@@ -1822,10 +1825,27 @@ function showDetectedApps(targets) {
|
|
|
1822
1825
|
`), "Detected apps");
|
|
1823
1826
|
}
|
|
1824
1827
|
function showCountingLocalChats() {
|
|
1825
|
-
|
|
1828
|
+
countingSpinner = Y2();
|
|
1829
|
+
countingSpinner.start("Scanning local chats");
|
|
1830
|
+
}
|
|
1831
|
+
function showCountingToolChats(tool) {
|
|
1832
|
+
countingSpinner?.message(`Scanning ${tool} chats`);
|
|
1833
|
+
}
|
|
1834
|
+
function showCountingToolProgress(tool, checked, found, total) {
|
|
1835
|
+
const checkedText = total ? `${checked.toLocaleString()}/${total.toLocaleString()}` : checked.toLocaleString();
|
|
1836
|
+
countingSpinner?.message(`Scanning ${tool}: ${checkedText} files, ${found.toLocaleString()} importable`);
|
|
1837
|
+
}
|
|
1838
|
+
function showCountingToolDone(tool, count) {
|
|
1839
|
+
toolTotals[tool] = count;
|
|
1840
|
+
countingSpinner?.message(`${tool}: ${count.toLocaleString()} chats`);
|
|
1826
1841
|
}
|
|
1827
1842
|
function showLocalChatsCounted() {
|
|
1828
|
-
|
|
1843
|
+
if (!countingSpinner)
|
|
1844
|
+
return;
|
|
1845
|
+
const entries = Object.entries(toolTotals).filter(([, n]) => n > 0);
|
|
1846
|
+
const summary = entries.length ? entries.map(([tool, n]) => `${tool} ${n.toLocaleString()}`).join(", ") : "no chats found";
|
|
1847
|
+
countingSpinner.stop(`Found ${summary}`);
|
|
1848
|
+
countingSpinner = null;
|
|
1829
1849
|
}
|
|
1830
1850
|
async function promptApiKey(options) {
|
|
1831
1851
|
if (options.providedApiKey) {
|
|
@@ -1916,8 +1936,10 @@ async function confirmBackgroundSync() {
|
|
|
1916
1936
|
}));
|
|
1917
1937
|
return value === "yes";
|
|
1918
1938
|
}
|
|
1939
|
+
var countingSpinner = null, toolTotals;
|
|
1919
1940
|
var init_interactive = __esm(() => {
|
|
1920
1941
|
init_dist2();
|
|
1942
|
+
toolTotals = {};
|
|
1921
1943
|
});
|
|
1922
1944
|
|
|
1923
1945
|
// src/index.ts
|
|
@@ -2049,39 +2071,58 @@ function getParentUuid(lines) {
|
|
|
2049
2071
|
}
|
|
2050
2072
|
return;
|
|
2051
2073
|
}
|
|
2052
|
-
function countImportableClaudeSessions() {
|
|
2074
|
+
async function countImportableClaudeSessions(onProgress) {
|
|
2053
2075
|
const projectsDir = join2(homedir2(), ".claude", "projects");
|
|
2054
2076
|
let count = 0;
|
|
2077
|
+
let checked = 0;
|
|
2078
|
+
let total = 0;
|
|
2055
2079
|
let projectDirs;
|
|
2056
2080
|
try {
|
|
2057
2081
|
projectDirs = readdirSync(projectsDir);
|
|
2058
2082
|
} catch {
|
|
2059
2083
|
return 0;
|
|
2060
2084
|
}
|
|
2061
|
-
|
|
2085
|
+
const projectFiles = projectDirs.map((projDir) => {
|
|
2062
2086
|
const projPath = join2(projectsDir, projDir);
|
|
2063
|
-
let files;
|
|
2064
2087
|
try {
|
|
2065
|
-
files = readdirSync(projPath).filter((f) => f.endsWith(".jsonl"));
|
|
2088
|
+
const files = readdirSync(projPath).filter((f) => f.endsWith(".jsonl"));
|
|
2089
|
+
total += files.length;
|
|
2090
|
+
return { projPath, files };
|
|
2066
2091
|
} catch {
|
|
2067
|
-
|
|
2092
|
+
return { projPath, files: [] };
|
|
2068
2093
|
}
|
|
2094
|
+
});
|
|
2095
|
+
const yieldToEventLoop = () => new Promise((resolve) => setImmediate(resolve));
|
|
2096
|
+
const checkpoint = async () => {
|
|
2097
|
+
onProgress?.({ checked, found: count, total });
|
|
2098
|
+
await yieldToEventLoop();
|
|
2099
|
+
};
|
|
2100
|
+
for (const { projPath, files } of projectFiles) {
|
|
2069
2101
|
for (const file of files) {
|
|
2102
|
+
checked++;
|
|
2070
2103
|
try {
|
|
2071
2104
|
const raw = readFileSync2(join2(projPath, file), "utf-8");
|
|
2072
2105
|
const lines = raw.split(`
|
|
2073
2106
|
`);
|
|
2074
2107
|
const parentUuid = getParentUuid(lines);
|
|
2075
|
-
if (parentUuid != null)
|
|
2108
|
+
if (parentUuid != null) {
|
|
2109
|
+
if (checked % 100 === 0)
|
|
2110
|
+
await checkpoint();
|
|
2076
2111
|
continue;
|
|
2112
|
+
}
|
|
2077
2113
|
const { turns } = parseSession(lines);
|
|
2078
2114
|
if (turns.length > 0)
|
|
2079
2115
|
count++;
|
|
2080
2116
|
} catch {
|
|
2117
|
+
if (checked % 100 === 0)
|
|
2118
|
+
await checkpoint();
|
|
2081
2119
|
continue;
|
|
2082
2120
|
}
|
|
2121
|
+
if (checked % 100 === 0)
|
|
2122
|
+
await checkpoint();
|
|
2083
2123
|
}
|
|
2084
2124
|
}
|
|
2125
|
+
onProgress?.({ checked, found: count, total });
|
|
2085
2126
|
return count;
|
|
2086
2127
|
}
|
|
2087
2128
|
function ingestClaude() {
|
|
@@ -2274,12 +2315,20 @@ function walkCodexSessionFiles(dir, visit) {
|
|
|
2274
2315
|
}
|
|
2275
2316
|
} catch {}
|
|
2276
2317
|
}
|
|
2277
|
-
function countImportableCodexSessions() {
|
|
2318
|
+
async function countImportableCodexSessions(onProgress) {
|
|
2278
2319
|
const sessionsDir = join3(homedir3(), ".codex", "sessions");
|
|
2279
2320
|
if (!existsSync3(sessionsDir))
|
|
2280
2321
|
return 0;
|
|
2281
|
-
|
|
2322
|
+
const files = [];
|
|
2282
2323
|
walkCodexSessionFiles(sessionsDir, (filePath) => {
|
|
2324
|
+
files.push(filePath);
|
|
2325
|
+
});
|
|
2326
|
+
const total = files.length;
|
|
2327
|
+
let count = 0;
|
|
2328
|
+
let checked = 0;
|
|
2329
|
+
const yieldToEventLoop = () => new Promise((resolve) => setImmediate(resolve));
|
|
2330
|
+
for (const filePath of files) {
|
|
2331
|
+
checked++;
|
|
2283
2332
|
try {
|
|
2284
2333
|
const lines = readFileSync3(filePath, "utf-8").split(`
|
|
2285
2334
|
`).filter(Boolean);
|
|
@@ -2287,7 +2336,12 @@ function countImportableCodexSessions() {
|
|
|
2287
2336
|
if (rounds.length > 0)
|
|
2288
2337
|
count++;
|
|
2289
2338
|
} catch {}
|
|
2290
|
-
|
|
2339
|
+
if (checked % 100 === 0) {
|
|
2340
|
+
onProgress?.({ checked, found: count, total });
|
|
2341
|
+
await yieldToEventLoop();
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
onProgress?.({ checked, found: count, total });
|
|
2291
2345
|
return count;
|
|
2292
2346
|
}
|
|
2293
2347
|
function walkCodexSessions(dir, memories, sessionIds, stats) {
|
|
@@ -2580,7 +2634,7 @@ async function openCursorKvDb(dbPath, fileSize, wasmDir) {
|
|
|
2580
2634
|
function formatMiB(bytes) {
|
|
2581
2635
|
return (bytes / 1024 / 1024).toFixed(0);
|
|
2582
2636
|
}
|
|
2583
|
-
async function countImportableCursorSessions(dbPath, wasmDir) {
|
|
2637
|
+
async function countImportableCursorSessions(dbPath, wasmDir, onProgress) {
|
|
2584
2638
|
let fileSize;
|
|
2585
2639
|
try {
|
|
2586
2640
|
fileSize = statSync(dbPath).size;
|
|
@@ -2594,22 +2648,36 @@ async function countImportableCursorSessions(dbPath, wasmDir) {
|
|
|
2594
2648
|
try {
|
|
2595
2649
|
const rows = db.selectComposerData();
|
|
2596
2650
|
let count = 0;
|
|
2651
|
+
let checked = 0;
|
|
2652
|
+
const total = rows.length;
|
|
2653
|
+
const report = () => {
|
|
2654
|
+
if (checked % 50 === 0 || checked === total) {
|
|
2655
|
+
onProgress?.({ checked, found: count, total });
|
|
2656
|
+
}
|
|
2657
|
+
};
|
|
2597
2658
|
for (const { key, value } of rows) {
|
|
2659
|
+
checked++;
|
|
2598
2660
|
const composerId = key.replace("composerData:", "");
|
|
2599
2661
|
let parsed;
|
|
2600
2662
|
try {
|
|
2601
2663
|
parsed = JSON.parse(value);
|
|
2602
|
-
if (!parsed || typeof parsed !== "object")
|
|
2664
|
+
if (!parsed || typeof parsed !== "object") {
|
|
2665
|
+
report();
|
|
2603
2666
|
continue;
|
|
2667
|
+
}
|
|
2604
2668
|
} catch {
|
|
2669
|
+
report();
|
|
2605
2670
|
continue;
|
|
2606
2671
|
}
|
|
2607
2672
|
const bubbleHeaders = parsed.fullConversationHeadersOnly;
|
|
2608
|
-
if (!Array.isArray(bubbleHeaders) || bubbleHeaders.length === 0)
|
|
2673
|
+
if (!Array.isArray(bubbleHeaders) || bubbleHeaders.length === 0) {
|
|
2674
|
+
report();
|
|
2609
2675
|
continue;
|
|
2676
|
+
}
|
|
2610
2677
|
const turns = extractTurns(db, composerId, bubbleHeaders);
|
|
2611
2678
|
if (turns.length > 0)
|
|
2612
2679
|
count++;
|
|
2680
|
+
report();
|
|
2613
2681
|
}
|
|
2614
2682
|
return count;
|
|
2615
2683
|
} finally {
|
|
@@ -2742,23 +2810,34 @@ async function ingestCursor(dbPath, wasmDir) {
|
|
|
2742
2810
|
}
|
|
2743
2811
|
|
|
2744
2812
|
// src/detect.ts
|
|
2745
|
-
async function detect() {
|
|
2813
|
+
async function detect(options = {}) {
|
|
2746
2814
|
const home = homedir5();
|
|
2747
2815
|
const os = platform3();
|
|
2748
2816
|
const tools = [];
|
|
2817
|
+
const onProgress = options.onProgress;
|
|
2749
2818
|
const claudeDir = join5(home, ".claude", "projects");
|
|
2750
2819
|
if (existsSync5(claudeDir)) {
|
|
2751
|
-
|
|
2820
|
+
onProgress?.({ tool: "Claude Code", status: "start" });
|
|
2821
|
+
const sessionCount = await countImportableClaudeSessions((progress) => {
|
|
2822
|
+
onProgress?.({ tool: "Claude Code", status: "progress", ...progress });
|
|
2823
|
+
});
|
|
2824
|
+
onProgress?.({ tool: "Claude Code", status: "done", count: sessionCount });
|
|
2752
2825
|
tools.push({ name: "Claude Code", id: "claude", available: sessionCount > 0, path: claudeDir, sessionCount, sessionCountApproximate: true });
|
|
2753
2826
|
} else {
|
|
2827
|
+
onProgress?.({ tool: "Claude Code", status: "skip", reason: "not found" });
|
|
2754
2828
|
tools.push({ name: "Claude Code", id: "claude", available: false, path: claudeDir, sessionCount: 0 });
|
|
2755
2829
|
}
|
|
2756
2830
|
const codexConfig = join5(home, ".codex", "config.toml");
|
|
2757
2831
|
const codexSessions = join5(home, ".codex", "sessions");
|
|
2758
2832
|
if (existsSync5(codexConfig) || existsSync5(codexSessions)) {
|
|
2759
|
-
|
|
2833
|
+
onProgress?.({ tool: "Codex", status: "start" });
|
|
2834
|
+
const sessionCount = await countImportableCodexSessions((progress) => {
|
|
2835
|
+
onProgress?.({ tool: "Codex", status: "progress", ...progress });
|
|
2836
|
+
});
|
|
2837
|
+
onProgress?.({ tool: "Codex", status: "done", count: sessionCount });
|
|
2760
2838
|
tools.push({ name: "Codex", id: "codex", available: true, path: codexConfig, sessionCount, sessionCountApproximate: true });
|
|
2761
2839
|
} else {
|
|
2840
|
+
onProgress?.({ tool: "Codex", status: "skip", reason: "not found" });
|
|
2762
2841
|
tools.push({ name: "Codex", id: "codex", available: false, path: codexConfig, sessionCount: 0 });
|
|
2763
2842
|
}
|
|
2764
2843
|
let cursorDbPath;
|
|
@@ -2769,12 +2848,22 @@ async function detect() {
|
|
|
2769
2848
|
} else {
|
|
2770
2849
|
cursorDbPath = join5(home, ".config", "Cursor", "User", "globalStorage", "state.vscdb");
|
|
2771
2850
|
}
|
|
2851
|
+
const cursorExists = existsSync5(cursorDbPath);
|
|
2852
|
+
if (cursorExists)
|
|
2853
|
+
onProgress?.({ tool: "Cursor", status: "start" });
|
|
2854
|
+
else
|
|
2855
|
+
onProgress?.({ tool: "Cursor", status: "skip", reason: "not found" });
|
|
2856
|
+
const cursorCount = cursorExists ? await countImportableCursorSessions(cursorDbPath, undefined, (progress) => {
|
|
2857
|
+
onProgress?.({ tool: "Cursor", status: "progress", ...progress });
|
|
2858
|
+
}) : 0;
|
|
2859
|
+
if (cursorExists)
|
|
2860
|
+
onProgress?.({ tool: "Cursor", status: "done", count: cursorCount });
|
|
2772
2861
|
tools.push({
|
|
2773
2862
|
name: "Cursor",
|
|
2774
2863
|
id: "cursor",
|
|
2775
|
-
available:
|
|
2864
|
+
available: cursorExists,
|
|
2776
2865
|
path: cursorDbPath,
|
|
2777
|
-
sessionCount:
|
|
2866
|
+
sessionCount: cursorCount,
|
|
2778
2867
|
sessionCountApproximate: true
|
|
2779
2868
|
});
|
|
2780
2869
|
const windsurfDir = join5(home, ".codeium", "windsurf");
|
|
@@ -3928,6 +4017,15 @@ function renderSourceBreakdown(memories) {
|
|
|
3928
4017
|
function formatSessionCount(count, approximate) {
|
|
3929
4018
|
return `${approximate ? "~" : ""}${count} sessions`;
|
|
3930
4019
|
}
|
|
4020
|
+
function renderDetectProgress(event) {
|
|
4021
|
+
if (event.status === "start") {
|
|
4022
|
+
showCountingToolChats(event.tool);
|
|
4023
|
+
} else if (event.status === "progress" && event.checked !== undefined && event.found !== undefined) {
|
|
4024
|
+
showCountingToolProgress(event.tool, event.checked, event.found, event.total);
|
|
4025
|
+
} else if (event.status === "done") {
|
|
4026
|
+
showCountingToolDone(event.tool, event.count ?? 0);
|
|
4027
|
+
}
|
|
4028
|
+
}
|
|
3931
4029
|
function parseArgs() {
|
|
3932
4030
|
const args = process.argv.slice(2);
|
|
3933
4031
|
let key = "";
|
|
@@ -4161,7 +4259,7 @@ async function main() {
|
|
|
4161
4259
|
}
|
|
4162
4260
|
}
|
|
4163
4261
|
showCountingLocalChats();
|
|
4164
|
-
const detectedTools = await detect();
|
|
4262
|
+
const detectedTools = await detect({ onProgress: renderDetectProgress });
|
|
4165
4263
|
showLocalChatsCounted();
|
|
4166
4264
|
interactiveTargets = MCP_TARGETS.map((target) => {
|
|
4167
4265
|
const detected = detectedTools.find((tool) => tool.id === target.id);
|