conare 0.1.1 → 0.1.2

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 +48 -31
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -376,12 +376,13 @@ function ingestClaude() {
376
376
  const projectsDir = join3(homedir3(), ".claude", "projects");
377
377
  const memories = [];
378
378
  const sessionIds = [];
379
- let skipped = 0;
379
+ let filtered = 0;
380
+ let deduped = 0;
380
381
  let projectDirs;
381
382
  try {
382
383
  projectDirs = readdirSync2(projectsDir);
383
384
  } catch {
384
- return { memories, sessionIds, skipped };
385
+ return { memories, sessionIds, skipped: 0, filtered, deduped };
385
386
  }
386
387
  for (const projDir of projectDirs) {
387
388
  const projPath = join3(projectsDir, projDir);
@@ -398,7 +399,7 @@ function ingestClaude() {
398
399
  const { turns, date } = parseSession(raw.split(`
399
400
  `));
400
401
  if (turns.length === 0) {
401
- skipped++;
402
+ filtered++;
402
403
  continue;
403
404
  }
404
405
  const header = `# Chat: ${project}${date ? ` | ${date}` : ""}`;
@@ -423,7 +424,7 @@ ${body}`;
423
424
  const dedupKey = `claude:${sessionId}`;
424
425
  const fingerprint = `${dedupKey}:${contentHash}`;
425
426
  if (isIngested("claude", fingerprint)) {
426
- skipped++;
427
+ deduped++;
427
428
  continue;
428
429
  }
429
430
  memories.push({
@@ -441,7 +442,7 @@ ${body}`;
441
442
  sessionIds.push(sessionId);
442
443
  }
443
444
  }
444
- return { memories, sessionIds, skipped };
445
+ return { memories, sessionIds, skipped: filtered + deduped, filtered, deduped };
445
446
  }
446
447
 
447
448
  // src/ingest/codex.ts
@@ -452,7 +453,8 @@ var MAX_CONTENT2 = 48000;
452
453
  function ingestCodex() {
453
454
  const memories = [];
454
455
  const sessionIds = [];
455
- let skipped = 0;
456
+ let filtered = 0;
457
+ let deduped = 0;
456
458
  const historyPath = join4(homedir4(), ".codex", "history.jsonl");
457
459
  if (existsSync3(historyPath)) {
458
460
  try {
@@ -490,14 +492,14 @@ ${body}`;
490
492
 
491
493
  [truncated]`;
492
494
  if (content.length < 100) {
493
- skipped++;
495
+ filtered++;
494
496
  continue;
495
497
  }
496
498
  const contentHash = createContentHash(content);
497
499
  const dedupKey = `codex:${sessionId}`;
498
500
  const fingerprint = `${dedupKey}:${contentHash}`;
499
501
  if (isIngested("codex", fingerprint)) {
500
- skipped++;
502
+ deduped++;
501
503
  continue;
502
504
  }
503
505
  memories.push({
@@ -512,16 +514,19 @@ ${body}`;
512
514
  const sessionsDir = join4(homedir4(), ".codex", "sessions");
513
515
  if (existsSync3(sessionsDir)) {
514
516
  try {
515
- walkCodexSessions(sessionsDir, memories, sessionIds, skipped);
517
+ const stats = { filtered: 0, deduped: 0 };
518
+ walkCodexSessions(sessionsDir, memories, sessionIds, stats);
519
+ filtered += stats.filtered;
520
+ deduped += stats.deduped;
516
521
  } catch {}
517
522
  }
518
- return { memories, sessionIds, skipped };
523
+ return { memories, sessionIds, skipped: filtered + deduped, filtered, deduped };
519
524
  }
520
- function walkCodexSessions(dir, memories, sessionIds, skipped) {
525
+ function walkCodexSessions(dir, memories, sessionIds, stats) {
521
526
  try {
522
527
  for (const entry of readdirSync3(dir, { withFileTypes: true })) {
523
528
  if (entry.isDirectory()) {
524
- walkCodexSessions(join4(dir, entry.name), memories, sessionIds, skipped);
529
+ walkCodexSessions(join4(dir, entry.name), memories, sessionIds, stats);
525
530
  } else if (entry.name.endsWith(".jsonl")) {
526
531
  const sessionId = basename2(entry.name, ".jsonl");
527
532
  if (sessionIds.includes(sessionId))
@@ -552,8 +557,10 @@ function walkCodexSessions(dir, memories, sessionIds, skipped) {
552
557
  continue;
553
558
  }
554
559
  }
555
- if (turns.length === 0)
560
+ if (turns.length === 0) {
561
+ stats.filtered++;
556
562
  continue;
563
+ }
557
564
  const body = turns.map((t) => t.length > 500 ? t.slice(0, 500) + "..." : t).join(`
558
565
 
559
566
  ---
@@ -570,6 +577,7 @@ ${body}`;
570
577
  const dedupKey = `codex:${sessionId}`;
571
578
  const fingerprint = `${dedupKey}:${contentHash}`;
572
579
  if (isIngested("codex", fingerprint)) {
580
+ stats.deduped++;
573
581
  continue;
574
582
  }
575
583
  memories.push({
@@ -649,17 +657,18 @@ function extractTurns(db, composerId, bubbleHeaders) {
649
657
  async function ingestCursor(dbPath, wasmDir) {
650
658
  const memories = [];
651
659
  const sessionIds = [];
652
- let skipped = 0;
660
+ let filtered = 0;
661
+ let deduped = 0;
653
662
  let fileSize;
654
663
  try {
655
664
  fileSize = statSync(dbPath).size;
656
665
  } catch {
657
666
  console.log(" Skipping Cursor: database not accessible");
658
- return { memories, sessionIds, skipped };
667
+ return { memories, sessionIds, skipped: 0, filtered, deduped };
659
668
  }
660
669
  if (fileSize > MAX_DB_SIZE) {
661
670
  console.log(` Skipping Cursor: database too large (${(fileSize / 1024 / 1024 / 1024).toFixed(1)}GB)`);
662
- return { memories, sessionIds, skipped };
671
+ return { memories, sessionIds, skipped: 0, filtered, deduped };
663
672
  }
664
673
  if (fileSize > WARN_DB_SIZE) {
665
674
  console.log(` Warning: large database (${(fileSize / 1024 / 1024).toFixed(0)}MB), loading into memory...`);
@@ -667,14 +676,14 @@ async function ingestCursor(dbPath, wasmDir) {
667
676
  const initSqlJs = loadSqlJs(wasmDir);
668
677
  if (!initSqlJs) {
669
678
  console.log(" Skipping Cursor: sql.js not available");
670
- return { memories, sessionIds, skipped };
679
+ return { memories, sessionIds, skipped: 0, filtered, deduped };
671
680
  }
672
681
  let db;
673
682
  try {
674
683
  db = await openDb(initSqlJs, dbPath, wasmDir);
675
684
  } catch (e) {
676
685
  console.log(` Skipping Cursor: cannot open database (${e.message})`);
677
- return { memories, sessionIds, skipped };
686
+ return { memories, sessionIds, skipped: 0, filtered, deduped };
678
687
  }
679
688
  try {
680
689
  let rows = [];
@@ -689,21 +698,21 @@ async function ingestCursor(dbPath, wasmDir) {
689
698
  try {
690
699
  parsed = JSON.parse(value);
691
700
  if (!parsed || typeof parsed !== "object") {
692
- skipped++;
701
+ filtered++;
693
702
  continue;
694
703
  }
695
704
  } catch {
696
- skipped++;
705
+ filtered++;
697
706
  continue;
698
707
  }
699
708
  const bubbleHeaders = parsed.fullConversationHeadersOnly;
700
709
  if (!Array.isArray(bubbleHeaders) || bubbleHeaders.length === 0) {
701
- skipped++;
710
+ filtered++;
702
711
  continue;
703
712
  }
704
713
  const turns = extractTurns(db, composerId, bubbleHeaders);
705
714
  if (turns.length === 0) {
706
- skipped++;
715
+ filtered++;
707
716
  continue;
708
717
  }
709
718
  const sessionName = parsed.name || "Cursor Chat";
@@ -730,7 +739,7 @@ ${body}`;
730
739
  const dedupKey = `cursor:${composerId}`;
731
740
  const fingerprint = `${dedupKey}:${contentHash}`;
732
741
  if (isIngested("cursor", fingerprint)) {
733
- skipped++;
742
+ deduped++;
734
743
  continue;
735
744
  }
736
745
  memories.push({
@@ -752,7 +761,7 @@ ${body}`;
752
761
  } finally {
753
762
  db.close();
754
763
  }
755
- return { memories, sessionIds, skipped };
764
+ return { memories, sessionIds, skipped: filtered + deduped, filtered, deduped };
756
765
  }
757
766
 
758
767
  // src/ingest/codebase.ts
@@ -1000,7 +1009,7 @@ function indexCodebase(rootPath) {
1000
1009
 
1001
1010
  // src/api.ts
1002
1011
  var API_URL = "https://mcp.conare.ai";
1003
- function createUploadBatches(memories, maxItems = 5, maxChars = 120000) {
1012
+ function createUploadBatches(memories, maxItems = 20, maxChars = 400000) {
1004
1013
  const batches = [];
1005
1014
  let current = [];
1006
1015
  let currentChars = 0;
@@ -1926,6 +1935,14 @@ function renderProgressSummary(success, failed, noun) {
1926
1935
  return `\r \x1B[32m✓\x1B[0m [\x1B[36m${bar}\x1B[0m] ${success} ${noun}, ${failed} failed (${pct}%)${" ".repeat(12)}
1927
1936
  `;
1928
1937
  }
1938
+ function renderDiscoverySummary(discovered, filtered, deduped) {
1939
+ const parts = [`${discovered} ingestible`];
1940
+ if (filtered > 0)
1941
+ parts.push(`${filtered} filtered`);
1942
+ if (deduped > 0)
1943
+ parts.push(`${deduped} already imported`);
1944
+ return parts.join(", ");
1945
+ }
1929
1946
  function parseArgs() {
1930
1947
  const args = process.argv.slice(2);
1931
1948
  let key = "";
@@ -2160,22 +2177,22 @@ Nothing new to index.`);
2160
2177
  const shouldIngest = (name) => selectedSources.includes(name);
2161
2178
  if (shouldIngest("claude") && tools.find((t) => t.name === "Claude Code")?.available) {
2162
2179
  process.stdout.write("Ingesting Claude Code... ");
2163
- const { memories, skipped } = ingestClaude();
2180
+ const { memories, filtered, deduped } = ingestClaude();
2164
2181
  allMemories.push(...memories);
2165
- console.log(`${memories.length} new, ${skipped} skipped`);
2182
+ console.log(renderDiscoverySummary(memories.length, filtered, deduped));
2166
2183
  }
2167
2184
  if (shouldIngest("codex") && tools.find((t) => t.name === "Codex")?.available) {
2168
2185
  process.stdout.write("Ingesting Codex... ");
2169
- const { memories, skipped } = ingestCodex();
2186
+ const { memories, filtered, deduped } = ingestCodex();
2170
2187
  allMemories.push(...memories);
2171
- console.log(`${memories.length} new, ${skipped} skipped`);
2188
+ console.log(renderDiscoverySummary(memories.length, filtered, deduped));
2172
2189
  }
2173
2190
  if (shouldIngest("cursor") && tools.find((t) => t.name === "Cursor")?.available) {
2174
2191
  process.stdout.write("Ingesting Cursor... ");
2175
2192
  const cursorTool = tools.find((t) => t.name === "Cursor");
2176
- const { memories, skipped } = await ingestCursor(cursorTool.path, opts.wasmDir);
2193
+ const { memories, filtered, deduped } = await ingestCursor(cursorTool.path, opts.wasmDir);
2177
2194
  allMemories.push(...memories);
2178
- console.log(`${memories.length} new, ${skipped} skipped`);
2195
+ console.log(renderDiscoverySummary(memories.length, filtered, deduped));
2179
2196
  }
2180
2197
  console.log();
2181
2198
  if (allMemories.length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "conare",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Conare CLI for ingesting AI chat history and configuring memory at conare.ai",
5
5
  "type": "module",
6
6
  "bin": {