conare 0.5.14 → 0.5.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +81 -47
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2055,6 +2055,42 @@ function parseSession(lines) {
2055
2055
  })).filter((t) => t.assistant.length >= MIN_TURN_LEN);
2056
2056
  return { turns, date, sourceTimestamp, startedAt, updatedAt };
2057
2057
  }
2058
+ function hasAnyImportableTurn(lines) {
2059
+ let currentUser = null;
2060
+ let currentAssistant = [];
2061
+ const closeRound = () => {
2062
+ if (currentUser === null || currentAssistant.length === 0)
2063
+ return false;
2064
+ const assistant = currentAssistant.filter((p) => !isNarration(p)).join(`
2065
+
2066
+ `);
2067
+ return assistant.length >= MIN_TURN_LEN;
2068
+ };
2069
+ for (const line of lines) {
2070
+ if (!line.trim())
2071
+ continue;
2072
+ let obj;
2073
+ try {
2074
+ obj = JSON.parse(line);
2075
+ } catch {
2076
+ continue;
2077
+ }
2078
+ if (obj.type === "user") {
2079
+ const text = cleanText(extractText(obj.message?.content));
2080
+ if (text.length >= MIN_TURN_LEN) {
2081
+ if (closeRound())
2082
+ return true;
2083
+ currentUser = text;
2084
+ currentAssistant = [];
2085
+ }
2086
+ } else if (obj.type === "assistant") {
2087
+ const text = cleanText(extractText(obj.message?.content));
2088
+ if (text.length >= MIN_TURN_LEN)
2089
+ currentAssistant.push(text);
2090
+ }
2091
+ }
2092
+ return closeRound();
2093
+ }
2058
2094
  function getParentUuid(lines) {
2059
2095
  for (const line of lines) {
2060
2096
  if (!line.trim())
@@ -2072,56 +2108,48 @@ function getParentUuid(lines) {
2072
2108
  return;
2073
2109
  }
2074
2110
  async function countImportableClaudeSessions(onProgress) {
2111
+ const { readFile } = await import("node:fs/promises");
2075
2112
  const projectsDir = join2(homedir2(), ".claude", "projects");
2076
- let count = 0;
2077
- let checked = 0;
2078
- let total = 0;
2079
2113
  let projectDirs;
2080
2114
  try {
2081
2115
  projectDirs = readdirSync(projectsDir);
2082
2116
  } catch {
2083
2117
  return 0;
2084
2118
  }
2085
- const projectFiles = projectDirs.map((projDir) => {
2119
+ const allFiles = [];
2120
+ for (const projDir of projectDirs) {
2086
2121
  const projPath = join2(projectsDir, projDir);
2087
2122
  try {
2088
- const files = readdirSync(projPath).filter((f) => f.endsWith(".jsonl"));
2089
- total += files.length;
2090
- return { projPath, files };
2091
- } catch {
2092
- return { projPath, files: [] };
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) {
2101
- for (const file of files) {
2102
- checked++;
2123
+ for (const f of readdirSync(projPath)) {
2124
+ if (f.endsWith(".jsonl"))
2125
+ allFiles.push(join2(projPath, f));
2126
+ }
2127
+ } catch {}
2128
+ }
2129
+ const total = allFiles.length;
2130
+ let count = 0;
2131
+ let checked = 0;
2132
+ const CONCURRENCY = 16;
2133
+ let nextIdx = 0;
2134
+ const worker = async () => {
2135
+ while (true) {
2136
+ const i = nextIdx++;
2137
+ if (i >= allFiles.length)
2138
+ return;
2103
2139
  try {
2104
- const raw = readFileSync2(join2(projPath, file), "utf-8");
2140
+ const raw = await readFile(allFiles[i], "utf-8");
2105
2141
  const lines = raw.split(`
2106
2142
  `);
2107
2143
  const parentUuid = getParentUuid(lines);
2108
- if (parentUuid != null) {
2109
- if (checked % 100 === 0)
2110
- await checkpoint();
2111
- continue;
2112
- }
2113
- const { turns } = parseSession(lines);
2114
- if (turns.length > 0)
2144
+ if (parentUuid == null && hasAnyImportableTurn(lines))
2115
2145
  count++;
2116
- } catch {
2117
- if (checked % 100 === 0)
2118
- await checkpoint();
2119
- continue;
2120
- }
2146
+ } catch {}
2147
+ checked++;
2121
2148
  if (checked % 100 === 0)
2122
- await checkpoint();
2149
+ onProgress?.({ checked, found: count, total });
2123
2150
  }
2124
- }
2151
+ };
2152
+ await Promise.all(Array.from({ length: CONCURRENCY }, () => worker()));
2125
2153
  onProgress?.({ checked, found: count, total });
2126
2154
  return count;
2127
2155
  }
@@ -2319,6 +2347,7 @@ async function countImportableCodexSessions(onProgress) {
2319
2347
  const sessionsDir = join3(homedir3(), ".codex", "sessions");
2320
2348
  if (!existsSync3(sessionsDir))
2321
2349
  return 0;
2350
+ const { readFile } = await import("node:fs/promises");
2322
2351
  const files = [];
2323
2352
  walkCodexSessionFiles(sessionsDir, (filePath) => {
2324
2353
  files.push(filePath);
@@ -2326,21 +2355,26 @@ async function countImportableCodexSessions(onProgress) {
2326
2355
  const total = files.length;
2327
2356
  let count = 0;
2328
2357
  let checked = 0;
2329
- const yieldToEventLoop = () => new Promise((resolve) => setImmediate(resolve));
2330
- for (const filePath of files) {
2331
- checked++;
2332
- try {
2333
- const lines = readFileSync3(filePath, "utf-8").split(`
2358
+ const CONCURRENCY = 16;
2359
+ let nextIdx = 0;
2360
+ const worker = async () => {
2361
+ while (true) {
2362
+ const i = nextIdx++;
2363
+ if (i >= files.length)
2364
+ return;
2365
+ try {
2366
+ const lines = (await readFile(files[i], "utf-8")).split(`
2334
2367
  `).filter(Boolean);
2335
- const { rounds } = parseCodexSession(lines);
2336
- if (rounds.length > 0)
2337
- count++;
2338
- } catch {}
2339
- if (checked % 100 === 0) {
2340
- onProgress?.({ checked, found: count, total });
2341
- await yieldToEventLoop();
2368
+ const { rounds } = parseCodexSession(lines);
2369
+ if (rounds.length > 0)
2370
+ count++;
2371
+ } catch {}
2372
+ checked++;
2373
+ if (checked % 100 === 0)
2374
+ onProgress?.({ checked, found: count, total });
2342
2375
  }
2343
- }
2376
+ };
2377
+ await Promise.all(Array.from({ length: CONCURRENCY }, () => worker()));
2344
2378
  onProgress?.({ checked, found: count, total });
2345
2379
  return count;
2346
2380
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "conare",
3
- "version": "0.5.14",
3
+ "version": "0.5.15",
4
4
  "description": "Conare CLI for indexing AI chat history and configuring memory at conare.ai",
5
5
  "type": "module",
6
6
  "bin": {