conare 0.5.10 → 0.5.11

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 +253 -66
  2. package/package.json +5 -2
package/dist/index.js CHANGED
@@ -693,7 +693,7 @@ var init_api = __esm(() => {
693
693
  };
694
694
  });
695
695
 
696
- // ../node_modules/sisteransi/src/index.js
696
+ // node_modules/sisteransi/src/index.js
697
697
  var require_src = __commonJS((exports, module) => {
698
698
  var ESC = "\x1B";
699
699
  var CSI = `${ESC}[`;
@@ -751,7 +751,7 @@ var require_src = __commonJS((exports, module) => {
751
751
  module.exports = { cursor, scroll, erase, beep };
752
752
  });
753
753
 
754
- // ../node_modules/picocolors/picocolors.js
754
+ // node_modules/picocolors/picocolors.js
755
755
  var require_picocolors = __commonJS((exports, module) => {
756
756
  var p = process || {};
757
757
  var argv = p.argv || [];
@@ -821,7 +821,7 @@ var require_picocolors = __commonJS((exports, module) => {
821
821
  module.exports.createColors = createColors;
822
822
  });
823
823
 
824
- // ../node_modules/@clack/core/dist/index.mjs
824
+ // node_modules/@clack/core/dist/index.mjs
825
825
  import { stdin as j, stdout as M } from "node:process";
826
826
  import * as g from "node:readline";
827
827
  import O from "node:readline";
@@ -1357,7 +1357,7 @@ var init_dist = __esm(() => {
1357
1357
  };
1358
1358
  });
1359
1359
 
1360
- // ../node_modules/@clack/prompts/dist/index.mjs
1360
+ // node_modules/@clack/prompts/dist/index.mjs
1361
1361
  var exports_dist = {};
1362
1362
  __export(exports_dist, {
1363
1363
  updateSettings: () => cD,
@@ -1875,7 +1875,7 @@ async function promptAuth(options) {
1875
1875
  }
1876
1876
  async function selectChatSources(targets) {
1877
1877
  return ensureValue(await fe({
1878
- message: "Select chat sources",
1878
+ message: "Select chat sources to index",
1879
1879
  required: false,
1880
1880
  initialValues: targets.filter((target) => target.available !== false && (target.detectedCount ?? 0) > 0).map((target) => target.id),
1881
1881
  options: targets.map((target) => ({
@@ -2337,12 +2337,13 @@ function walkCodexSessions(dir, memories, sessionIds, stats) {
2337
2337
 
2338
2338
  // src/ingest/cursor.ts
2339
2339
  init_shared();
2340
+ import { Buffer } from "node:buffer";
2340
2341
  import { existsSync as existsSync4, readFileSync as readFileSync4, statSync } from "node:fs";
2341
2342
  import { dirname, join as join4 } from "node:path";
2342
2343
  import { createRequire as createRequire2 } from "node:module";
2343
2344
  import { homedir as homedir4 } from "node:os";
2344
- var MAX_DB_SIZE = 2 * 1024 * 1024 * 1024;
2345
- var WARN_DB_SIZE = 500 * 1024 * 1024;
2345
+ var MAX_SQLJS_DB_SIZE = 2 * 1024 * 1024 * 1024;
2346
+ var LARGE_SQLJS_DB_SIZE = 500 * 1024 * 1024;
2346
2347
  var MIN_TURN_LEN2 = 50;
2347
2348
  function parseCursorTimestamp(value) {
2348
2349
  const parsed = parseTimestampMs(value);
@@ -2375,45 +2376,217 @@ function resolveSqlJsWasmDir(wasmDir) {
2375
2376
  return existsSync4(join4(installedBundleDir, "sql.js", "package.json")) ? installedBundleDir : undefined;
2376
2377
  }
2377
2378
  }
2378
- function openDb(initSqlJs, dbPath, wasmDir) {
2379
+ function toText(value) {
2380
+ if (typeof value === "string")
2381
+ return value;
2382
+ if (value instanceof Uint8Array)
2383
+ return Buffer.from(value).toString("utf-8");
2384
+ if (value === null || value === undefined)
2385
+ return "";
2386
+ return String(value);
2387
+ }
2388
+ function normalizeKvRow(row) {
2389
+ const key = toText(row.key);
2390
+ const value = toText(row.value);
2391
+ return key ? { key, value } : null;
2392
+ }
2393
+ function normalizeRows(rows) {
2394
+ return rows.map(normalizeKvRow).filter((row) => row !== null);
2395
+ }
2396
+ async function openBunSqliteDb(dbPath) {
2397
+ let raw;
2398
+ try {
2399
+ const mod = await import("bun:sqlite");
2400
+ const Database = mod.Database;
2401
+ if (!Database)
2402
+ return null;
2403
+ raw = new Database(dbPath, { readonly: true });
2404
+ const composerStmt = raw.query("SELECT key, value FROM cursorDiskKV WHERE key LIKE ?");
2405
+ const valueStmt = raw.query("SELECT value FROM cursorDiskKV WHERE key = ? LIMIT 1");
2406
+ return {
2407
+ kind: "bun:sqlite",
2408
+ selectComposerData() {
2409
+ return normalizeRows(composerStmt.all("composerData:%"));
2410
+ },
2411
+ selectValue(key) {
2412
+ const row = valueStmt.get(key);
2413
+ if (!row)
2414
+ return null;
2415
+ const value = toText(row.value);
2416
+ return value || null;
2417
+ },
2418
+ close() {
2419
+ raw.close();
2420
+ }
2421
+ };
2422
+ } catch {
2423
+ try {
2424
+ raw?.close();
2425
+ } catch {}
2426
+ return null;
2427
+ }
2428
+ }
2429
+ function openBetterSqliteDb(dbPath) {
2430
+ let raw;
2431
+ try {
2432
+ const require2 = createRequire2(import.meta.url);
2433
+ const BetterSqlite3 = require2("better-sqlite3");
2434
+ raw = new BetterSqlite3(dbPath, { readonly: true, fileMustExist: true });
2435
+ raw.pragma("query_only = ON");
2436
+ const composerStmt = raw.prepare("SELECT key, value FROM cursorDiskKV WHERE key LIKE ?");
2437
+ const valueStmt = raw.prepare("SELECT value FROM cursorDiskKV WHERE key = ? LIMIT 1");
2438
+ return {
2439
+ kind: "better-sqlite3",
2440
+ selectComposerData() {
2441
+ return normalizeRows(composerStmt.all("composerData:%"));
2442
+ },
2443
+ selectValue(key) {
2444
+ const row = valueStmt.get(key);
2445
+ if (!row)
2446
+ return null;
2447
+ const value = toText(row.value);
2448
+ return value || null;
2449
+ },
2450
+ close() {
2451
+ raw.close();
2452
+ }
2453
+ };
2454
+ } catch {
2455
+ try {
2456
+ raw?.close();
2457
+ } catch {}
2458
+ return null;
2459
+ }
2460
+ }
2461
+ async function importNodeSqlite() {
2462
+ const originalEmitWarning = process.emitWarning;
2463
+ try {
2464
+ process.emitWarning = function(warning, ...args) {
2465
+ const message = typeof warning === "string" ? warning : warning && typeof warning === "object" && ("message" in warning) ? String(warning.message) : "";
2466
+ const type = typeof args[0] === "string" ? args[0] : args[0]?.type;
2467
+ if (type === "ExperimentalWarning" && message.includes("SQLite"))
2468
+ return;
2469
+ return originalEmitWarning.call(process, warning, ...args);
2470
+ };
2471
+ return await import("node:sqlite");
2472
+ } catch {
2473
+ return null;
2474
+ } finally {
2475
+ process.emitWarning = originalEmitWarning;
2476
+ }
2477
+ }
2478
+ async function openNodeSqliteDb(dbPath) {
2479
+ let raw;
2480
+ try {
2481
+ const mod = await importNodeSqlite();
2482
+ const DatabaseSync = mod?.DatabaseSync;
2483
+ if (!DatabaseSync)
2484
+ return null;
2485
+ raw = new DatabaseSync(dbPath, { readOnly: true });
2486
+ const composerStmt = raw.prepare("SELECT key, value FROM cursorDiskKV WHERE key LIKE ?");
2487
+ const valueStmt = raw.prepare("SELECT value FROM cursorDiskKV WHERE key = ? LIMIT 1");
2488
+ return {
2489
+ kind: "node:sqlite",
2490
+ selectComposerData() {
2491
+ return normalizeRows(composerStmt.all("composerData:%"));
2492
+ },
2493
+ selectValue(key) {
2494
+ const row = valueStmt.get(key);
2495
+ if (!row)
2496
+ return null;
2497
+ const value = toText(row.value);
2498
+ return value || null;
2499
+ },
2500
+ close() {
2501
+ raw.close();
2502
+ }
2503
+ };
2504
+ } catch {
2505
+ try {
2506
+ raw?.close();
2507
+ } catch {}
2508
+ return null;
2509
+ }
2510
+ }
2511
+ function allowLargeSqlJsLoad() {
2512
+ const value = process.env.CONARE_CURSOR_ALLOW_SQLJS_LARGE;
2513
+ return value === "1" || value === "true";
2514
+ }
2515
+ async function openSqlJsDb(initSqlJs, dbPath, wasmDir) {
2379
2516
  const locateOpts = {};
2380
2517
  if (wasmDir) {
2381
2518
  locateOpts.locateFile = (file) => join4(wasmDir, "sql.js", "dist", file);
2382
2519
  }
2383
- return initSqlJs(locateOpts).then((SQL) => {
2384
- const buffer = readFileSync4(dbPath);
2385
- return new SQL.Database(buffer);
2386
- });
2520
+ const SQL = await initSqlJs(locateOpts);
2521
+ const buffer = readFileSync4(dbPath);
2522
+ const raw = new SQL.Database(buffer);
2523
+ function select(sql, params) {
2524
+ const stmt = raw.prepare(sql);
2525
+ try {
2526
+ stmt.bind(params);
2527
+ const rows = [];
2528
+ while (stmt.step()) {
2529
+ rows.push(stmt.getAsObject());
2530
+ }
2531
+ return rows;
2532
+ } finally {
2533
+ stmt.free();
2534
+ }
2535
+ }
2536
+ return {
2537
+ kind: "sql.js",
2538
+ selectComposerData() {
2539
+ return normalizeRows(select("SELECT key, value FROM cursorDiskKV WHERE key LIKE ?", ["composerData:%"]));
2540
+ },
2541
+ selectValue(key) {
2542
+ const row = select("SELECT value FROM cursorDiskKV WHERE key = ? LIMIT 1", [key])[0];
2543
+ if (!row)
2544
+ return null;
2545
+ const value = toText(row.value);
2546
+ return value || null;
2547
+ },
2548
+ close() {
2549
+ raw.close();
2550
+ }
2551
+ };
2387
2552
  }
2388
- async function countImportableCursorSessions(dbPath, wasmDir) {
2389
- try {
2390
- const fileSize = statSync(dbPath).size;
2391
- if (fileSize > MAX_DB_SIZE)
2392
- return 0;
2393
- } catch {
2394
- return 0;
2553
+ async function openCursorKvDb(dbPath, fileSize, wasmDir) {
2554
+ const nativeDb = await openBunSqliteDb(dbPath) || openBetterSqliteDb(dbPath) || await openNodeSqliteDb(dbPath);
2555
+ if (nativeDb)
2556
+ return { db: nativeDb };
2557
+ if (fileSize > MAX_SQLJS_DB_SIZE)
2558
+ return { db: null, reason: "sqljs-too-large" };
2559
+ if (fileSize > LARGE_SQLJS_DB_SIZE && !allowLargeSqlJsLoad()) {
2560
+ return { db: null, reason: "sqljs-large" };
2395
2561
  }
2396
2562
  const effectiveWasmDir = resolveSqlJsWasmDir(wasmDir);
2397
2563
  const initSqlJs = loadSqlJs(effectiveWasmDir);
2398
2564
  if (!initSqlJs)
2399
- return 0;
2400
- let db;
2565
+ return { db: null, reason: "no-driver" };
2401
2566
  try {
2402
- db = await openDb(initSqlJs, dbPath, effectiveWasmDir);
2567
+ return { db: await openSqlJsDb(initSqlJs, dbPath, effectiveWasmDir) };
2568
+ } catch (e) {
2569
+ return { db: null, reason: "open-failed", message: e?.message || String(e) };
2570
+ }
2571
+ }
2572
+ function formatMiB(bytes) {
2573
+ return (bytes / 1024 / 1024).toFixed(0);
2574
+ }
2575
+ async function countImportableCursorSessions(dbPath, wasmDir) {
2576
+ let fileSize;
2577
+ try {
2578
+ fileSize = statSync(dbPath).size;
2403
2579
  } catch {
2404
2580
  return 0;
2405
2581
  }
2582
+ const openResult = await openCursorKvDb(dbPath, fileSize, wasmDir);
2583
+ if (!openResult.db)
2584
+ return 0;
2585
+ const db = openResult.db;
2406
2586
  try {
2407
- let rows = [];
2408
- try {
2409
- const results = db.exec("SELECT key, value FROM cursorDiskKV WHERE key LIKE 'composerData:%'");
2410
- if (results.length > 0)
2411
- rows = results[0].values;
2412
- } catch {
2413
- return 0;
2414
- }
2587
+ const rows = db.selectComposerData();
2415
2588
  let count = 0;
2416
- for (const [key, value] of rows) {
2589
+ for (const { key, value } of rows) {
2417
2590
  const composerId = key.replace("composerData:", "");
2418
2591
  let parsed;
2419
2592
  try {
@@ -2441,11 +2614,11 @@ function extractTurns(db, composerId, bubbleHeaders) {
2441
2614
  for (const header of bubbleHeaders) {
2442
2615
  let text = "";
2443
2616
  try {
2444
- const result = db.exec(`SELECT value FROM cursorDiskKV WHERE key = 'bubbleId:${composerId}:${header.bubbleId}'`);
2445
- if (result.length > 0) {
2446
- const bubble = JSON.parse(result[0].values[0][0]);
2447
- text = cleanText(bubble.text || "");
2448
- }
2617
+ const rawBubble = db.selectValue(`bubbleId:${composerId}:${header.bubbleId}`);
2618
+ if (!rawBubble)
2619
+ continue;
2620
+ const bubble = JSON.parse(rawBubble);
2621
+ text = cleanText(bubble.text || "");
2449
2622
  } catch {
2450
2623
  continue;
2451
2624
  }
@@ -2472,34 +2645,33 @@ async function ingestCursor(dbPath, wasmDir) {
2472
2645
  console.log(" Skipping Cursor: database not accessible");
2473
2646
  return { memories, sessionIds, skipped: 0, filtered, deduped };
2474
2647
  }
2475
- if (fileSize > MAX_DB_SIZE) {
2476
- console.log(` Skipping Cursor: database too large (${(fileSize / 1024 / 1024 / 1024).toFixed(1)}GB)`);
2648
+ const openResult = await openCursorKvDb(dbPath, fileSize, wasmDir);
2649
+ if (!openResult.db) {
2650
+ if (openResult.reason === "sqljs-too-large") {
2651
+ console.log(` Skipping Cursor: database too large (${(fileSize / 1024 / 1024 / 1024).toFixed(1)}GB)`);
2652
+ } else if (openResult.reason === "sqljs-large") {
2653
+ console.log(` Skipping Cursor: large database (${formatMiB(fileSize)}MB) requires streaming SQLite support; not loading it into memory`);
2654
+ } else if (openResult.reason === "no-driver") {
2655
+ console.log(" Skipping Cursor: SQLite support not available");
2656
+ } else {
2657
+ console.log(` Skipping Cursor: cannot open database (${openResult.message || "unknown error"})`);
2658
+ }
2477
2659
  return { memories, sessionIds, skipped: 0, filtered, deduped };
2478
2660
  }
2479
- if (fileSize > WARN_DB_SIZE) {
2480
- console.log(` Warning: large database (${(fileSize / 1024 / 1024).toFixed(0)}MB), loading into memory...`);
2661
+ if (openResult.db.kind === "sql.js" && fileSize > LARGE_SQLJS_DB_SIZE) {
2662
+ console.log(` Warning: large database (${formatMiB(fileSize)}MB), loading into memory via sql.js fallback...`);
2481
2663
  }
2482
- const effectiveWasmDir = resolveSqlJsWasmDir(wasmDir);
2483
- const initSqlJs = loadSqlJs(effectiveWasmDir);
2484
- if (!initSqlJs) {
2485
- console.log(" Skipping Cursor: sql.js not available");
2486
- return { memories, sessionIds, skipped: 0, filtered, deduped };
2487
- }
2488
- let db;
2489
- try {
2490
- db = await openDb(initSqlJs, dbPath, effectiveWasmDir);
2491
- } catch (e) {
2492
- console.log(` Skipping Cursor: cannot open database (${e.message})`);
2664
+ const db = openResult.db;
2665
+ if (fileSize > MAX_SQLJS_DB_SIZE && db.kind === "sql.js") {
2666
+ console.log(` Skipping Cursor: database too large (${(fileSize / 1024 / 1024 / 1024).toFixed(1)}GB)`);
2493
2667
  return { memories, sessionIds, skipped: 0, filtered, deduped };
2494
2668
  }
2495
2669
  try {
2496
2670
  let rows = [];
2497
2671
  try {
2498
- const results = db.exec("SELECT key, value FROM cursorDiskKV WHERE key LIKE 'composerData:%'");
2499
- if (results.length > 0)
2500
- rows = results[0].values;
2672
+ rows = db.selectComposerData();
2501
2673
  } catch {}
2502
- for (const [key, value] of rows) {
2674
+ for (const { key, value } of rows) {
2503
2675
  const composerId = key.replace("composerData:", "");
2504
2676
  let parsed;
2505
2677
  try {
@@ -3190,6 +3362,7 @@ import { existsSync as existsSync9, mkdirSync as mkdirSync4, writeFileSync as wr
3190
3362
  import { join as join9, dirname as dirname3 } from "node:path";
3191
3363
  import { homedir as homedir8, platform as platform6 } from "node:os";
3192
3364
  import { execSync as execSync3 } from "node:child_process";
3365
+ import { createRequire as createRequire3 } from "node:module";
3193
3366
  var CONARE_DIR = join9(homedir8(), ".conare");
3194
3367
  var BIN_DIR = join9(CONARE_DIR, "bin");
3195
3368
  var CONFIG_PATH2 = join9(CONARE_DIR, "config.json");
@@ -3342,12 +3515,9 @@ function persistBinary(apiKey) {
3342
3515
  const dest = join9(BIN_DIR, "conare-ingest.mjs");
3343
3516
  const content = readFileSync8(cliEntry, "utf-8");
3344
3517
  writeFileSync4(dest, content);
3345
- const sqlJsDir = findSqlJs();
3346
- if (sqlJsDir) {
3347
- const targetDir = join9(BIN_DIR, "node_modules", "sql.js");
3348
- mkdirSync4(targetDir, { recursive: true });
3518
+ for (const moduleName of ["sql.js", "better-sqlite3", "bindings", "file-uri-to-path"]) {
3349
3519
  try {
3350
- cpSync(sqlJsDir, targetDir, { recursive: true });
3520
+ copyNodeModule(moduleName);
3351
3521
  } catch {}
3352
3522
  }
3353
3523
  const runShPath = join9(BIN_DIR, "run.sh");
@@ -3387,11 +3557,15 @@ function findCliBundle() {
3387
3557
  return entry;
3388
3558
  return null;
3389
3559
  }
3390
- function findSqlJs() {
3560
+ function findNodeModule(name) {
3561
+ try {
3562
+ const require2 = createRequire3(import.meta.url);
3563
+ return dirname3(require2.resolve(`${name}/package.json`));
3564
+ } catch {}
3391
3565
  const candidates = [
3392
- join9(process.cwd(), "node_modules", "sql.js"),
3393
- join9(dirname3(new URL(import.meta.url).pathname), "..", "node_modules", "sql.js"),
3394
- join9(dirname3(new URL(import.meta.url).pathname), "..", "..", "node_modules", "sql.js")
3566
+ join9(process.cwd(), "node_modules", name),
3567
+ join9(dirname3(new URL(import.meta.url).pathname), "..", "node_modules", name),
3568
+ join9(dirname3(new URL(import.meta.url).pathname), "..", "..", "node_modules", name)
3395
3569
  ];
3396
3570
  for (const c of candidates) {
3397
3571
  if (existsSync9(c))
@@ -3399,6 +3573,15 @@ function findSqlJs() {
3399
3573
  }
3400
3574
  return null;
3401
3575
  }
3576
+ function copyNodeModule(name) {
3577
+ const sourceDir = findNodeModule(name);
3578
+ if (!sourceDir)
3579
+ return;
3580
+ const targetDir = join9(BIN_DIR, "node_modules", name);
3581
+ rmSync2(targetDir, { recursive: true, force: true });
3582
+ mkdirSync4(dirname3(targetDir), { recursive: true });
3583
+ cpSync(sourceDir, targetDir, { recursive: true });
3584
+ }
3402
3585
  function cleanupOldLaunchAgent() {
3403
3586
  try {
3404
3587
  execSync3(`launchctl bootout gui/${uid()} "${PLIST_PATH}" 2>/dev/null`, { stdio: "ignore" });
@@ -3737,6 +3920,9 @@ function renderSourceBreakdown(memories) {
3737
3920
  function formatSessionCount(count, approximate) {
3738
3921
  return `${approximate ? "~" : ""}${count} sessions`;
3739
3922
  }
3923
+ function nextTick() {
3924
+ return new Promise((resolve2) => setTimeout(resolve2, 0));
3925
+ }
3740
3926
  function parseArgs() {
3741
3927
  const args = process.argv.slice(2);
3742
3928
  let key = "";
@@ -3970,9 +4156,10 @@ async function main() {
3970
4156
  }
3971
4157
  }
3972
4158
  const detectSpinner = Y2();
3973
- detectSpinner.start("Detecting apps...");
4159
+ detectSpinner.start("Counting local chats...");
4160
+ await nextTick();
3974
4161
  const detectedTools = await detect();
3975
- detectSpinner.stop("Apps detected");
4162
+ detectSpinner.stop("Local chats counted");
3976
4163
  interactiveTargets = MCP_TARGETS.map((target) => {
3977
4164
  const detected = detectedTools.find((tool) => tool.id === target.id);
3978
4165
  return {
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "conare",
3
- "version": "0.5.10",
3
+ "version": "0.5.11",
4
4
  "description": "Conare CLI for indexing AI chat history and configuring memory at conare.ai",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "conare": "./dist/index.js"
8
8
  },
9
9
  "scripts": {
10
- "build": "bun build src/index.ts --outdir dist --target node --format esm --external sql.js",
10
+ "build": "bun build src/index.ts --outdir dist --target node --format esm --external sql.js --external better-sqlite3",
11
11
  "prepublishOnly": "bun run build"
12
12
  },
13
13
  "files": [
@@ -28,5 +28,8 @@
28
28
  "dependencies": {
29
29
  "@clack/prompts": "^0.11.0",
30
30
  "sql.js": "^1.12.0"
31
+ },
32
+ "optionalDependencies": {
33
+ "better-sqlite3": "^12.10.0"
31
34
  }
32
35
  }