conare 0.5.6 → 0.5.7

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 +521 -446
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -48,10 +48,10 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
48
48
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
49
49
 
50
50
  // src/ingest/shared.ts
51
- import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "node:fs";
51
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
52
52
  import { createHash } from "node:crypto";
53
- import { join as join2 } from "node:path";
54
- import { homedir as homedir2 } from "node:os";
53
+ import { join } from "node:path";
54
+ import { homedir } from "node:os";
55
55
  function fitContent(header, rounds) {
56
56
  const buildContent = (maxUser) => {
57
57
  const body = rounds.map((r) => {
@@ -112,8 +112,8 @@ function createContentHash(content) {
112
112
  }
113
113
  function getIngested() {
114
114
  try {
115
- if (existsSync2(MANIFEST_PATH)) {
116
- return JSON.parse(readFileSync2(MANIFEST_PATH, "utf-8"));
115
+ if (existsSync(MANIFEST_PATH)) {
116
+ return JSON.parse(readFileSync(MANIFEST_PATH, "utf-8"));
117
117
  }
118
118
  } catch {}
119
119
  return {};
@@ -124,8 +124,8 @@ function markIngested(source, sessionIds) {
124
124
  for (const id of sessionIds)
125
125
  existing.add(id);
126
126
  manifest[source] = [...existing];
127
- const dir = join2(homedir2(), ".conare");
128
- if (!existsSync2(dir))
127
+ const dir = join(homedir(), ".conare");
128
+ if (!existsSync(dir))
129
129
  mkdirSync(dir, { recursive: true });
130
130
  writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2));
131
131
  }
@@ -141,14 +141,14 @@ function clearIngested(source) {
141
141
  for (const key of Object.keys(manifest))
142
142
  delete manifest[key];
143
143
  }
144
- const dir = join2(homedir2(), ".conare");
145
- if (!existsSync2(dir))
144
+ const dir = join(homedir(), ".conare");
145
+ if (!existsSync(dir))
146
146
  mkdirSync(dir, { recursive: true });
147
147
  writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2));
148
148
  }
149
149
  var MANIFEST_PATH, MAX_MEMORY_CONTENT = 200000, TRUNCATED_USER_MSG = 3000, MIN_SUBSTANTIVE = 200, NARRATION_RE;
150
150
  var init_shared = __esm(() => {
151
- MANIFEST_PATH = join2(homedir2(), ".conare", "ingested.json");
151
+ MANIFEST_PATH = join(homedir(), ".conare", "ingested.json");
152
152
  NARRATION_RE = /^[\s\n]*(Let me |Now let me |Now I['\u2019]|Now add |Now fix |Now replace |Now integrate |Now update |Now pass |Now clean |Now build|Update the |Builds clean|Deployed\.|Wait, I |Let['\u2019]s test |Good —|Great\.|Perfect\.|Alright|OK,? let me|I[''\u2019]ll |Starting |I need to |Need |I found |I read |I[''\u2019]ve (loaded|confirmed|verified)|Context loaded|Next (I[''\u2019]|step)|Deps confirm|Diff check|Still missing|I[''\u2019]ll (do|check|inspect|trace|run|grab|pull|read|verify))/;
153
153
  });
154
154
 
@@ -161,16 +161,16 @@ __export(exports_codebase, {
161
161
  detectProjectName: () => detectProjectName
162
162
  });
163
163
  import { createHash as createHash2 } from "node:crypto";
164
- import { readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync2, existsSync as existsSync5 } from "node:fs";
164
+ import { readdirSync as readdirSync4, readFileSync as readFileSync5, statSync as statSync2, existsSync as existsSync6 } from "node:fs";
165
165
  import { join as join6, relative, extname, resolve, basename as basename3 } from "node:path";
166
166
  import { execSync as execSync2 } from "node:child_process";
167
167
  function parseGitignore(rootPath) {
168
168
  const patterns = new Set;
169
169
  const gitignorePath = join6(rootPath, ".gitignore");
170
- if (!existsSync5(gitignorePath))
170
+ if (!existsSync6(gitignorePath))
171
171
  return patterns;
172
172
  try {
173
- const content = readFileSync6(gitignorePath, "utf-8");
173
+ const content = readFileSync5(gitignorePath, "utf-8");
174
174
  for (const line of content.split(`
175
175
  `)) {
176
176
  const trimmed = line.trim();
@@ -206,15 +206,15 @@ ${content}
206
206
  function detectProjectName(rootPath) {
207
207
  const readers = [
208
208
  () => {
209
- const pkg = JSON.parse(readFileSync6(join6(rootPath, "package.json"), "utf-8"));
209
+ const pkg = JSON.parse(readFileSync5(join6(rootPath, "package.json"), "utf-8"));
210
210
  return typeof pkg.name === "string" ? pkg.name : null;
211
211
  },
212
212
  () => {
213
- const content = readFileSync6(join6(rootPath, "Cargo.toml"), "utf-8");
213
+ const content = readFileSync5(join6(rootPath, "Cargo.toml"), "utf-8");
214
214
  return content.match(/^name\s*=\s*"([^"]+)"/m)?.[1] ?? null;
215
215
  },
216
216
  () => {
217
- const content = readFileSync6(join6(rootPath, "pyproject.toml"), "utf-8");
217
+ const content = readFileSync5(join6(rootPath, "pyproject.toml"), "utf-8");
218
218
  return content.match(/^name\s*=\s*"([^"]+)"/m)?.[1] ?? null;
219
219
  }
220
220
  ];
@@ -311,7 +311,7 @@ function indexCodebase(rootPath, options = {}) {
311
311
  }
312
312
  let raw;
313
313
  try {
314
- raw = readFileSync6(fullPath, "utf-8");
314
+ raw = readFileSync5(fullPath, "utf-8");
315
315
  } catch {
316
316
  skipped++;
317
317
  continue;
@@ -1790,10 +1790,10 @@ __export(exports_interactive, {
1790
1790
  finishSetup: () => finishSetup,
1791
1791
  confirmBackgroundSync: () => confirmBackgroundSync
1792
1792
  });
1793
- function formatDetectedCount(count) {
1793
+ function formatDetectedCount(count, approximate = false) {
1794
1794
  if (count === undefined)
1795
1795
  return "available";
1796
- return `${count.toLocaleString()} chats`;
1796
+ return `${approximate ? "~" : ""}${count.toLocaleString()} chats`;
1797
1797
  }
1798
1798
  function ensureValue(value) {
1799
1799
  if (pD(value)) {
@@ -1809,7 +1809,7 @@ function finishSetup() {
1809
1809
  Se("Starting setup...");
1810
1810
  }
1811
1811
  function showDetectedApps(targets) {
1812
- Me(targets.map((target) => `• ${target.label}: ${target.available === false ? "not detected" : formatDetectedCount(target.detectedCount)}`).join(`
1812
+ Me(targets.map((target) => `• ${target.label}: ${target.available === false ? "not detected" : formatDetectedCount(target.detectedCount, target.detectedCountApproximate)}`).join(`
1813
1813
  `), "Detected apps");
1814
1814
  }
1815
1815
  async function promptApiKey(options) {
@@ -1874,7 +1874,7 @@ async function selectChatSources(targets) {
1874
1874
  options: targets.map((target) => ({
1875
1875
  value: target.id,
1876
1876
  label: target.label,
1877
- hint: target.available === false ? "not detected" : formatDetectedCount(target.detectedCount)
1877
+ hint: target.available === false ? "not detected" : formatDetectedCount(target.detectedCount, target.detectedCountApproximate)
1878
1878
  }))
1879
1879
  }));
1880
1880
  }
@@ -1906,271 +1906,23 @@ var init_interactive = __esm(() => {
1906
1906
  });
1907
1907
 
1908
1908
  // src/index.ts
1909
- import { existsSync as existsSync9 } from "node:fs";
1909
+ import { existsSync as existsSync10 } from "node:fs";
1910
1910
  import { join as join10 } from "node:path";
1911
1911
 
1912
1912
  // src/detect.ts
1913
- import { existsSync, readdirSync, readFileSync } from "node:fs";
1914
- import { join } from "node:path";
1915
- import { homedir, platform } from "node:os";
1916
- import { createRequire as createRequire2 } from "node:module";
1917
- function countJsonlFiles(dir) {
1918
- let count = 0;
1919
- try {
1920
- for (const entry of readdirSync(dir, { withFileTypes: true })) {
1921
- if (entry.isDirectory()) {
1922
- count += countJsonlFiles(join(dir, entry.name));
1923
- } else if (entry.name.endsWith(".jsonl")) {
1924
- count++;
1925
- }
1926
- }
1927
- } catch {}
1928
- return count;
1929
- }
1930
- async function countCursorSessions(dbPath) {
1931
- try {
1932
- const require2 = createRequire2(import.meta.url);
1933
- const initSqlJs = require2("sql.js");
1934
- const SQL = await initSqlJs();
1935
- const buffer = readFileSync(dbPath);
1936
- const db = new SQL.Database(buffer);
1937
- try {
1938
- const results = db.exec("SELECT key, value FROM cursorDiskKV WHERE key LIKE 'composerData:%'");
1939
- if (results.length === 0)
1940
- return 0;
1941
- let count = 0;
1942
- for (const [, value] of results[0].values) {
1943
- try {
1944
- const parsed = JSON.parse(value);
1945
- const headers = parsed.fullConversationHeadersOnly;
1946
- if (!Array.isArray(headers) || headers.length < 2)
1947
- continue;
1948
- const hasUser = headers.some((h) => h.type === 1);
1949
- const hasAssistant = headers.some((h) => h.type === 2);
1950
- if (hasUser && hasAssistant)
1951
- count++;
1952
- } catch {
1953
- continue;
1954
- }
1955
- }
1956
- return count;
1957
- } finally {
1958
- db.close();
1959
- }
1960
- } catch {
1961
- return 0;
1962
- }
1963
- }
1964
- async function detect() {
1965
- const home = homedir();
1966
- const os = platform();
1967
- const tools = [];
1968
- const claudeDir = join(home, ".claude", "projects");
1969
- if (existsSync(claudeDir)) {
1970
- const sessionCount = countJsonlFiles(claudeDir);
1971
- tools.push({ name: "Claude Code", id: "claude", available: sessionCount > 0, path: claudeDir, sessionCount });
1972
- } else {
1973
- tools.push({ name: "Claude Code", id: "claude", available: false, path: claudeDir, sessionCount: 0 });
1974
- }
1975
- const codexConfig = join(home, ".codex", "config.toml");
1976
- const codexHistory = join(home, ".codex", "history.jsonl");
1977
- const codexSessions = join(home, ".codex", "sessions");
1978
- if (existsSync(codexConfig) || existsSync(codexHistory) || existsSync(codexSessions)) {
1979
- let sessionCount = 0;
1980
- if (existsSync(codexHistory)) {
1981
- try {
1982
- const lines = readFileSync(codexHistory, "utf-8").split(`
1983
- `).filter(Boolean);
1984
- const sessions = new Set(lines.map((l) => {
1985
- try {
1986
- return JSON.parse(l).session_id;
1987
- } catch {
1988
- return null;
1989
- }
1990
- }));
1991
- sessions.delete(null);
1992
- sessionCount = sessions.size;
1993
- } catch {}
1994
- }
1995
- tools.push({ name: "Codex", id: "codex", available: true, path: codexConfig, sessionCount });
1996
- } else {
1997
- tools.push({ name: "Codex", id: "codex", available: false, path: codexConfig, sessionCount: 0 });
1998
- }
1999
- let cursorDbPath;
2000
- if (os === "darwin") {
2001
- cursorDbPath = join(home, "Library", "Application Support", "Cursor", "User", "globalStorage", "state.vscdb");
2002
- } else if (os === "win32") {
2003
- cursorDbPath = join(process.env.APPDATA || join(home, "AppData", "Roaming"), "Cursor", "User", "globalStorage", "state.vscdb");
2004
- } else {
2005
- cursorDbPath = join(home, ".config", "Cursor", "User", "globalStorage", "state.vscdb");
2006
- }
2007
- tools.push({
2008
- name: "Cursor",
2009
- id: "cursor",
2010
- available: existsSync(cursorDbPath),
2011
- path: cursorDbPath,
2012
- sessionCount: existsSync(cursorDbPath) ? await countCursorSessions(cursorDbPath) : 0
2013
- });
2014
- const windsurfDir = join(home, ".codeium", "windsurf");
2015
- tools.push({
2016
- name: "Windsurf",
2017
- id: "windsurf",
2018
- available: existsSync(windsurfDir),
2019
- path: join(windsurfDir, "mcp_config.json"),
2020
- sessionCount: 0
2021
- });
2022
- let vscodePath;
2023
- if (os === "darwin") {
2024
- vscodePath = join(home, "Library", "Application Support", "Code");
2025
- } else if (os === "win32") {
2026
- vscodePath = join(process.env.APPDATA || join(home, "AppData", "Roaming"), "Code");
2027
- } else {
2028
- vscodePath = join(home, ".config", "Code");
2029
- }
2030
- tools.push({
2031
- name: "VS Code Copilot",
2032
- id: "vscode",
2033
- available: existsSync(vscodePath),
2034
- path: join(vscodePath, "User", "mcp.json"),
2035
- sessionCount: 0
2036
- });
2037
- let clinePath;
2038
- if (os === "darwin") {
2039
- clinePath = join(home, "Library", "Application Support", "Code", "User", "globalStorage", "saoudrizwan.claude-dev");
2040
- } else if (os === "win32") {
2041
- clinePath = join(process.env.APPDATA || join(home, "AppData", "Roaming"), "Code", "User", "globalStorage", "saoudrizwan.claude-dev");
2042
- } else {
2043
- clinePath = join(home, ".config", "Code", "User", "globalStorage", "saoudrizwan.claude-dev");
2044
- }
2045
- tools.push({
2046
- name: "Cline",
2047
- id: "cline",
2048
- available: existsSync(clinePath),
2049
- path: join(clinePath, "settings", "cline_mcp_settings.json"),
2050
- sessionCount: 0
2051
- });
2052
- const zedPath = os === "darwin" ? join(home, ".zed") : join(home, ".config", "zed");
2053
- tools.push({
2054
- name: "Zed",
2055
- id: "zed",
2056
- available: existsSync(zedPath),
2057
- path: join(zedPath, "settings.json"),
2058
- sessionCount: 0
2059
- });
2060
- const openclawDir = join(home, ".openclaw");
2061
- tools.push({
2062
- name: "OpenClaw",
2063
- id: "openclaw",
2064
- available: existsSync(openclawDir),
2065
- path: join(openclawDir, "openclaw.json"),
2066
- sessionCount: 0
2067
- });
2068
- const antigravityDir = join(home, ".gemini", "antigravity");
2069
- const antigravityConvDir = join(antigravityDir, "conversations");
2070
- let antigravityCount = 0;
2071
- if (existsSync(antigravityConvDir)) {
2072
- try {
2073
- antigravityCount = readdirSync(antigravityConvDir).filter((f) => f.endsWith(".pb")).length;
2074
- } catch {}
2075
- }
2076
- tools.push({
2077
- name: "Antigravity",
2078
- id: "antigravity",
2079
- available: existsSync(antigravityDir),
2080
- path: join(antigravityDir, "mcp_config.json"),
2081
- sessionCount: antigravityCount
2082
- });
2083
- return tools;
2084
- }
2085
-
2086
- // src/auth.ts
2087
- import { execSync } from "node:child_process";
2088
- import { platform as platform2 } from "node:os";
2089
- var API_URL = "https://conare.ai";
2090
- async function browserAuth() {
2091
- const stateBytes = new Uint8Array(16);
2092
- crypto.getRandomValues(stateBytes);
2093
- const state = Array.from(stateBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
2094
- const sessionRes = await fetch(`${API_URL}/api/auth/cli-session`, {
2095
- method: "POST",
2096
- headers: { "Content-Type": "application/json" },
2097
- body: JSON.stringify({ state })
2098
- });
2099
- if (!sessionRes.ok) {
2100
- throw new Error(`Failed to create auth session: HTTP ${sessionRes.status}`);
2101
- }
2102
- const { code, expiresAt } = await sessionRes.json();
2103
- const authUrl = `${API_URL}/cli-auth?code=${code}&state=${state}`;
2104
- const opened = openBrowser(authUrl);
2105
- if (!opened) {
2106
- console.log("");
2107
- console.log(" Open this URL in your browser to sign in:");
2108
- console.log("");
2109
- console.log(` ${authUrl}`);
2110
- console.log("");
2111
- }
2112
- const timeout = Math.max(expiresAt - Date.now(), 0);
2113
- const deadline = Date.now() + timeout;
2114
- while (Date.now() < deadline) {
2115
- await sleep(2000);
2116
- const exchangeRes = await fetch(`${API_URL}/api/auth/cli-exchange`, {
2117
- method: "POST",
2118
- headers: { "Content-Type": "application/json" },
2119
- body: JSON.stringify({ code, state })
2120
- });
2121
- if (exchangeRes.status === 202) {
2122
- continue;
2123
- }
2124
- if (exchangeRes.ok) {
2125
- const data = await exchangeRes.json();
2126
- return data.apiKey;
2127
- }
2128
- if (exchangeRes.status === 410) {
2129
- throw new Error("Authentication code was already used. Please try again.");
2130
- }
2131
- if (exchangeRes.status === 404) {
2132
- throw new Error("Authentication session expired. Please try again.");
2133
- }
2134
- throw new Error(`Authentication failed: HTTP ${exchangeRes.status}`);
2135
- }
2136
- throw new Error("Authentication timed out. Please try again.");
2137
- }
2138
- function openBrowser(url) {
2139
- try {
2140
- const os = platform2();
2141
- if (os === "darwin") {
2142
- execSync(`open "${url}"`, { stdio: "ignore" });
2143
- } else if (os === "win32") {
2144
- execSync(`start "" "${url}"`, { stdio: "ignore" });
2145
- } else {
2146
- try {
2147
- execSync(`xdg-open "${url}"`, { stdio: "ignore" });
2148
- } catch {
2149
- try {
2150
- execSync(`wslview "${url}"`, { stdio: "ignore" });
2151
- } catch {
2152
- return false;
2153
- }
2154
- }
2155
- }
2156
- return true;
2157
- } catch {
2158
- return false;
2159
- }
2160
- }
2161
- function sleep(ms) {
2162
- return new Promise((resolve) => setTimeout(resolve, ms));
2163
- }
1913
+ import { existsSync as existsSync5, readdirSync as readdirSync3 } from "node:fs";
1914
+ import { join as join5 } from "node:path";
1915
+ import { homedir as homedir5, platform as platform3 } from "node:os";
2164
1916
 
2165
1917
  // src/ingest/claude.ts
2166
1918
  init_shared();
2167
- import { readdirSync as readdirSync2, readFileSync as readFileSync3, existsSync as existsSync3 } from "node:fs";
2168
- import { join as join3, basename } from "node:path";
2169
- import { homedir as homedir3, platform as platform3 } from "node:os";
1919
+ import { readdirSync, readFileSync as readFileSync2, existsSync as existsSync2 } from "node:fs";
1920
+ import { join as join2, basename } from "node:path";
1921
+ import { homedir as homedir2, platform } from "node:os";
2170
1922
  var MIN_TURN_LEN = 50;
2171
1923
  function resolveProjectName(dirName) {
2172
1924
  const segments = dirName.replace(/^-/, "").split("-");
2173
- const isWindows = platform3() === "win32";
1925
+ const isWindows = platform() === "win32";
2174
1926
  let resolved;
2175
1927
  let startIdx;
2176
1928
  if (isWindows && segments.length > 0 && /^[A-Za-z]$/.test(segments[0])) {
@@ -2185,8 +1937,8 @@ function resolveProjectName(dirName) {
2185
1937
  let found = false;
2186
1938
  for (let end = segments.length;end > i; end--) {
2187
1939
  const candidate = segments.slice(i, end).join("-");
2188
- const candidatePath = join3(resolved, candidate);
2189
- if (existsSync3(candidatePath)) {
1940
+ const candidatePath = join2(resolved, candidate);
1941
+ if (existsSync2(candidatePath)) {
2190
1942
  resolved = candidatePath;
2191
1943
  i = end;
2192
1944
  found = true;
@@ -2194,11 +1946,11 @@ function resolveProjectName(dirName) {
2194
1946
  }
2195
1947
  }
2196
1948
  if (!found) {
2197
- resolved = join3(resolved, segments[i]);
1949
+ resolved = join2(resolved, segments[i]);
2198
1950
  i++;
2199
1951
  }
2200
1952
  }
2201
- const home = homedir3();
1953
+ const home = homedir2();
2202
1954
  const sep = isWindows ? "\\" : "/";
2203
1955
  if (resolved.startsWith(home + sep)) {
2204
1956
  return resolved.slice(home.length + 1).replace(/\\/g, "/");
@@ -2282,30 +2034,65 @@ function getParentUuid(lines) {
2282
2034
  }
2283
2035
  return;
2284
2036
  }
2037
+ function countImportableClaudeSessions() {
2038
+ const projectsDir = join2(homedir2(), ".claude", "projects");
2039
+ let count = 0;
2040
+ let projectDirs;
2041
+ try {
2042
+ projectDirs = readdirSync(projectsDir);
2043
+ } catch {
2044
+ return 0;
2045
+ }
2046
+ for (const projDir of projectDirs) {
2047
+ const projPath = join2(projectsDir, projDir);
2048
+ let files;
2049
+ try {
2050
+ files = readdirSync(projPath).filter((f) => f.endsWith(".jsonl"));
2051
+ } catch {
2052
+ continue;
2053
+ }
2054
+ for (const file of files) {
2055
+ try {
2056
+ const raw = readFileSync2(join2(projPath, file), "utf-8");
2057
+ const lines = raw.split(`
2058
+ `);
2059
+ const parentUuid = getParentUuid(lines);
2060
+ if (parentUuid != null)
2061
+ continue;
2062
+ const { turns } = parseSession(lines);
2063
+ if (turns.length > 0)
2064
+ count++;
2065
+ } catch {
2066
+ continue;
2067
+ }
2068
+ }
2069
+ }
2070
+ return count;
2071
+ }
2285
2072
  function ingestClaude() {
2286
- const projectsDir = join3(homedir3(), ".claude", "projects");
2073
+ const projectsDir = join2(homedir2(), ".claude", "projects");
2287
2074
  const memories = [];
2288
2075
  const sessionIds = [];
2289
2076
  let filtered = 0;
2290
2077
  let deduped = 0;
2291
2078
  let projectDirs;
2292
2079
  try {
2293
- projectDirs = readdirSync2(projectsDir);
2080
+ projectDirs = readdirSync(projectsDir);
2294
2081
  } catch {
2295
2082
  return { memories, sessionIds, skipped: 0, filtered, deduped };
2296
2083
  }
2297
2084
  for (const projDir of projectDirs) {
2298
- const projPath = join3(projectsDir, projDir);
2085
+ const projPath = join2(projectsDir, projDir);
2299
2086
  const project = resolveProjectName(projDir);
2300
2087
  let files;
2301
2088
  try {
2302
- files = readdirSync2(projPath).filter((f) => f.endsWith(".jsonl"));
2089
+ files = readdirSync(projPath).filter((f) => f.endsWith(".jsonl"));
2303
2090
  } catch {
2304
2091
  continue;
2305
2092
  }
2306
2093
  for (const file of files) {
2307
2094
  const sessionId = basename(file, ".jsonl");
2308
- const raw = readFileSync3(join3(projPath, file), "utf-8");
2095
+ const raw = readFileSync2(join2(projPath, file), "utf-8");
2309
2096
  const lines = raw.split(`
2310
2097
  `);
2311
2098
  const parentUuid = getParentUuid(lines);
@@ -2351,9 +2138,9 @@ function ingestClaude() {
2351
2138
 
2352
2139
  // src/ingest/codex.ts
2353
2140
  init_shared();
2354
- import { existsSync as existsSync4, readFileSync as readFileSync4, readdirSync as readdirSync3 } from "node:fs";
2355
- import { join as join4, basename as basename2 } from "node:path";
2356
- import { homedir as homedir4 } from "node:os";
2141
+ import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "node:fs";
2142
+ import { join as join3, basename as basename2 } from "node:path";
2143
+ import { homedir as homedir3 } from "node:os";
2357
2144
  function isCodexBoilerplate(text) {
2358
2145
  return text.startsWith("# AGENTS.md instructions for") || text.startsWith("<INSTRUCTIONS>") || text.startsWith("<user_instructions>") || text.startsWith("<user_action>");
2359
2146
  }
@@ -2362,7 +2149,7 @@ function extractCwd(text) {
2362
2149
  return match ? match[1] : null;
2363
2150
  }
2364
2151
  function projectFromCwd(cwd) {
2365
- const home = homedir4();
2152
+ const home = homedir3();
2366
2153
  const normalized = cwd.replace(/\\/g, "/");
2367
2154
  const normalizedHome = home.replace(/\\/g, "/");
2368
2155
  if (normalized.startsWith(normalizedHome + "/")) {
@@ -2375,8 +2162,8 @@ function ingestCodex() {
2375
2162
  const sessionIds = [];
2376
2163
  let filtered = 0;
2377
2164
  let deduped = 0;
2378
- const sessionsDir = join4(homedir4(), ".codex", "sessions");
2379
- if (existsSync4(sessionsDir)) {
2165
+ const sessionsDir = join3(homedir3(), ".codex", "sessions");
2166
+ if (existsSync3(sessionsDir)) {
2380
2167
  try {
2381
2168
  const stats = { filtered: 0, deduped: 0 };
2382
2169
  walkCodexSessions(sessionsDir, memories, sessionIds, stats);
@@ -2386,87 +2173,119 @@ function ingestCodex() {
2386
2173
  }
2387
2174
  return { memories, sessionIds, skipped: filtered + deduped, filtered, deduped };
2388
2175
  }
2176
+ function parseCodexSession(lines) {
2177
+ let date = null;
2178
+ let startedAt = null;
2179
+ let updatedAt = null;
2180
+ let sourceTimestamp = null;
2181
+ let project = null;
2182
+ const rounds = [];
2183
+ let currentUser = null;
2184
+ let currentAssistant = [];
2185
+ for (const line of lines) {
2186
+ try {
2187
+ const obj = JSON.parse(line);
2188
+ if (typeof obj.timestamp === "string") {
2189
+ if (!startedAt)
2190
+ startedAt = obj.timestamp;
2191
+ updatedAt = obj.timestamp;
2192
+ const parsed = parseTimestampMs(obj.timestamp);
2193
+ if (parsed !== null)
2194
+ sourceTimestamp = parsed;
2195
+ date = obj.timestamp.slice(0, 10);
2196
+ }
2197
+ if (obj.type === "session_meta" && obj.payload?.cwd) {
2198
+ project = projectFromCwd(obj.payload.cwd);
2199
+ }
2200
+ let role;
2201
+ let msgContent;
2202
+ if (obj.type === "response_item" && obj.payload?.type === "message") {
2203
+ role = obj.payload.role;
2204
+ msgContent = Array.isArray(obj.payload.content) ? obj.payload.content : undefined;
2205
+ } else if (obj.type === "message" && obj.role) {
2206
+ role = obj.role;
2207
+ msgContent = Array.isArray(obj.content) ? obj.content : undefined;
2208
+ }
2209
+ if (!role || !msgContent)
2210
+ continue;
2211
+ if (role === "user") {
2212
+ for (const block of msgContent) {
2213
+ if (block.type === "input_text" && block.text) {
2214
+ if (!project) {
2215
+ const cwd = extractCwd(block.text);
2216
+ if (cwd)
2217
+ project = projectFromCwd(cwd);
2218
+ }
2219
+ const text = cleanText(block.text);
2220
+ if (isCodexBoilerplate(text))
2221
+ continue;
2222
+ if (text.length >= 50) {
2223
+ if (currentUser !== null && currentAssistant.length > 0) {
2224
+ rounds.push({ user: currentUser, assistantParts: currentAssistant });
2225
+ }
2226
+ currentUser = text;
2227
+ currentAssistant = [];
2228
+ }
2229
+ }
2230
+ }
2231
+ } else if (role === "assistant") {
2232
+ for (const block of msgContent) {
2233
+ if (block.type === "output_text" && block.text) {
2234
+ const text = cleanText(block.text);
2235
+ if (!isNarration(text)) {
2236
+ currentAssistant.push(text);
2237
+ }
2238
+ }
2239
+ }
2240
+ }
2241
+ } catch {
2242
+ continue;
2243
+ }
2244
+ }
2245
+ if (currentUser !== null && currentAssistant.length > 0) {
2246
+ rounds.push({ user: currentUser, assistantParts: currentAssistant });
2247
+ }
2248
+ return { rounds, date, startedAt, updatedAt, sourceTimestamp, project };
2249
+ }
2250
+ function walkCodexSessionFiles(dir, visit) {
2251
+ try {
2252
+ for (const entry of readdirSync2(dir, { withFileTypes: true })) {
2253
+ const fullPath = join3(dir, entry.name);
2254
+ if (entry.isDirectory()) {
2255
+ walkCodexSessionFiles(fullPath, visit);
2256
+ } else if (entry.name.endsWith(".jsonl")) {
2257
+ visit(fullPath);
2258
+ }
2259
+ }
2260
+ } catch {}
2261
+ }
2262
+ function countImportableCodexSessions() {
2263
+ const sessionsDir = join3(homedir3(), ".codex", "sessions");
2264
+ if (!existsSync3(sessionsDir))
2265
+ return 0;
2266
+ let count = 0;
2267
+ walkCodexSessionFiles(sessionsDir, (filePath) => {
2268
+ try {
2269
+ const lines = readFileSync3(filePath, "utf-8").split(`
2270
+ `).filter(Boolean);
2271
+ const { rounds } = parseCodexSession(lines);
2272
+ if (rounds.length > 0)
2273
+ count++;
2274
+ } catch {}
2275
+ });
2276
+ return count;
2277
+ }
2389
2278
  function walkCodexSessions(dir, memories, sessionIds, stats) {
2390
2279
  try {
2391
- for (const entry of readdirSync3(dir, { withFileTypes: true })) {
2280
+ for (const entry of readdirSync2(dir, { withFileTypes: true })) {
2392
2281
  if (entry.isDirectory()) {
2393
- walkCodexSessions(join4(dir, entry.name), memories, sessionIds, stats);
2282
+ walkCodexSessions(join3(dir, entry.name), memories, sessionIds, stats);
2394
2283
  } else if (entry.name.endsWith(".jsonl")) {
2395
2284
  const sessionId = basename2(entry.name, ".jsonl");
2396
2285
  try {
2397
- const lines = readFileSync4(join4(dir, entry.name), "utf-8").split(`
2286
+ const lines = readFileSync3(join3(dir, entry.name), "utf-8").split(`
2398
2287
  `).filter(Boolean);
2399
- let date = null;
2400
- let startedAt = null;
2401
- let updatedAt = null;
2402
- let sourceTimestamp = null;
2403
- let project = null;
2404
- const rounds = [];
2405
- let currentUser = null;
2406
- let currentAssistant = [];
2407
- for (const line of lines) {
2408
- try {
2409
- const obj = JSON.parse(line);
2410
- if (typeof obj.timestamp === "string") {
2411
- if (!startedAt)
2412
- startedAt = obj.timestamp;
2413
- updatedAt = obj.timestamp;
2414
- const parsed = parseTimestampMs(obj.timestamp);
2415
- if (parsed !== null)
2416
- sourceTimestamp = parsed;
2417
- date = obj.timestamp.slice(0, 10);
2418
- }
2419
- if (obj.type === "session_meta" && obj.payload?.cwd) {
2420
- project = projectFromCwd(obj.payload.cwd);
2421
- }
2422
- let role;
2423
- let msgContent;
2424
- if (obj.type === "response_item" && obj.payload?.type === "message") {
2425
- role = obj.payload.role;
2426
- msgContent = Array.isArray(obj.payload.content) ? obj.payload.content : undefined;
2427
- } else if (obj.type === "message" && obj.role) {
2428
- role = obj.role;
2429
- msgContent = Array.isArray(obj.content) ? obj.content : undefined;
2430
- }
2431
- if (!role || !msgContent)
2432
- continue;
2433
- if (role === "user") {
2434
- for (const block of msgContent) {
2435
- if (block.type === "input_text" && block.text) {
2436
- if (!project) {
2437
- const cwd = extractCwd(block.text);
2438
- if (cwd)
2439
- project = projectFromCwd(cwd);
2440
- }
2441
- const text = cleanText(block.text);
2442
- if (isCodexBoilerplate(text))
2443
- continue;
2444
- if (text.length >= 50) {
2445
- if (currentUser !== null && currentAssistant.length > 0) {
2446
- rounds.push({ user: currentUser, assistantParts: currentAssistant });
2447
- }
2448
- currentUser = text;
2449
- currentAssistant = [];
2450
- }
2451
- }
2452
- }
2453
- } else if (role === "assistant") {
2454
- for (const block of msgContent) {
2455
- if (block.type === "output_text" && block.text) {
2456
- const text = cleanText(block.text);
2457
- if (!isNarration(text)) {
2458
- currentAssistant.push(text);
2459
- }
2460
- }
2461
- }
2462
- }
2463
- } catch {
2464
- continue;
2465
- }
2466
- }
2467
- if (currentUser !== null && currentAssistant.length > 0) {
2468
- rounds.push({ user: currentUser, assistantParts: currentAssistant });
2469
- }
2288
+ const { rounds, date, startedAt, updatedAt, sourceTimestamp, project } = parseCodexSession(lines);
2470
2289
  if (rounds.length === 0) {
2471
2290
  stats.filtered++;
2472
2291
  continue;
@@ -2511,9 +2330,10 @@ function walkCodexSessions(dir, memories, sessionIds, stats) {
2511
2330
 
2512
2331
  // src/ingest/cursor.ts
2513
2332
  init_shared();
2514
- import { readFileSync as readFileSync5, statSync } from "node:fs";
2515
- import { join as join5 } from "node:path";
2516
- import { createRequire as createRequire3 } from "node:module";
2333
+ import { existsSync as existsSync4, readFileSync as readFileSync4, statSync } from "node:fs";
2334
+ import { dirname, join as join4 } from "node:path";
2335
+ import { createRequire as createRequire2 } from "node:module";
2336
+ import { homedir as homedir4 } from "node:os";
2517
2337
  var MAX_DB_SIZE = 2 * 1024 * 1024 * 1024;
2518
2338
  var WARN_DB_SIZE = 500 * 1024 * 1024;
2519
2339
  var MIN_TURN_LEN2 = 50;
@@ -2526,26 +2346,88 @@ function parseCursorTimestamp(value) {
2526
2346
  function loadSqlJs(wasmDir) {
2527
2347
  try {
2528
2348
  if (wasmDir) {
2529
- const require2 = createRequire3(join5(wasmDir, "sql.js", "package.json"));
2349
+ const require2 = createRequire2(join4(wasmDir, "sql.js", "package.json"));
2530
2350
  return require2("sql.js");
2531
2351
  } else {
2532
- const require2 = createRequire3(import.meta.url);
2352
+ const require2 = createRequire2(import.meta.url);
2533
2353
  return require2("sql.js");
2534
2354
  }
2535
2355
  } catch {
2536
2356
  return null;
2537
2357
  }
2538
2358
  }
2359
+ function resolveSqlJsWasmDir(wasmDir) {
2360
+ if (wasmDir)
2361
+ return wasmDir;
2362
+ try {
2363
+ const require2 = createRequire2(import.meta.url);
2364
+ const packageJson = require2.resolve("sql.js/package.json");
2365
+ return dirname(dirname(packageJson));
2366
+ } catch {
2367
+ const installedBundleDir = join4(homedir4(), ".conare", "bin", "node_modules");
2368
+ return existsSync4(join4(installedBundleDir, "sql.js", "package.json")) ? installedBundleDir : undefined;
2369
+ }
2370
+ }
2539
2371
  function openDb(initSqlJs, dbPath, wasmDir) {
2540
2372
  const locateOpts = {};
2541
2373
  if (wasmDir) {
2542
- locateOpts.locateFile = (file) => join5(wasmDir, "sql.js", "dist", file);
2374
+ locateOpts.locateFile = (file) => join4(wasmDir, "sql.js", "dist", file);
2543
2375
  }
2544
2376
  return initSqlJs(locateOpts).then((SQL) => {
2545
- const buffer = readFileSync5(dbPath);
2377
+ const buffer = readFileSync4(dbPath);
2546
2378
  return new SQL.Database(buffer);
2547
2379
  });
2548
2380
  }
2381
+ async function countImportableCursorSessions(dbPath, wasmDir) {
2382
+ try {
2383
+ const fileSize = statSync(dbPath).size;
2384
+ if (fileSize > MAX_DB_SIZE)
2385
+ return 0;
2386
+ } catch {
2387
+ return 0;
2388
+ }
2389
+ const effectiveWasmDir = resolveSqlJsWasmDir(wasmDir);
2390
+ const initSqlJs = loadSqlJs(effectiveWasmDir);
2391
+ if (!initSqlJs)
2392
+ return 0;
2393
+ let db;
2394
+ try {
2395
+ db = await openDb(initSqlJs, dbPath, effectiveWasmDir);
2396
+ } catch {
2397
+ return 0;
2398
+ }
2399
+ try {
2400
+ let rows = [];
2401
+ try {
2402
+ const results = db.exec("SELECT key, value FROM cursorDiskKV WHERE key LIKE 'composerData:%'");
2403
+ if (results.length > 0)
2404
+ rows = results[0].values;
2405
+ } catch {
2406
+ return 0;
2407
+ }
2408
+ let count = 0;
2409
+ for (const [key, value] of rows) {
2410
+ const composerId = key.replace("composerData:", "");
2411
+ let parsed;
2412
+ try {
2413
+ parsed = JSON.parse(value);
2414
+ if (!parsed || typeof parsed !== "object")
2415
+ continue;
2416
+ } catch {
2417
+ continue;
2418
+ }
2419
+ const bubbleHeaders = parsed.fullConversationHeadersOnly;
2420
+ if (!Array.isArray(bubbleHeaders) || bubbleHeaders.length === 0)
2421
+ continue;
2422
+ const turns = extractTurns(db, composerId, bubbleHeaders);
2423
+ if (turns.length > 0)
2424
+ count++;
2425
+ }
2426
+ return count;
2427
+ } finally {
2428
+ db.close();
2429
+ }
2430
+ }
2549
2431
  function extractTurns(db, composerId, bubbleHeaders) {
2550
2432
  const turns = [];
2551
2433
  let pendingUser = null;
@@ -2590,14 +2472,15 @@ async function ingestCursor(dbPath, wasmDir) {
2590
2472
  if (fileSize > WARN_DB_SIZE) {
2591
2473
  console.log(` Warning: large database (${(fileSize / 1024 / 1024).toFixed(0)}MB), loading into memory...`);
2592
2474
  }
2593
- const initSqlJs = loadSqlJs(wasmDir);
2475
+ const effectiveWasmDir = resolveSqlJsWasmDir(wasmDir);
2476
+ const initSqlJs = loadSqlJs(effectiveWasmDir);
2594
2477
  if (!initSqlJs) {
2595
2478
  console.log(" Skipping Cursor: sql.js not available");
2596
2479
  return { memories, sessionIds, skipped: 0, filtered, deduped };
2597
2480
  }
2598
2481
  let db;
2599
2482
  try {
2600
- db = await openDb(initSqlJs, dbPath, wasmDir);
2483
+ db = await openDb(initSqlJs, dbPath, effectiveWasmDir);
2601
2484
  } catch (e) {
2602
2485
  console.log(` Skipping Cursor: cannot open database (${e.message})`);
2603
2486
  return { memories, sessionIds, skipped: 0, filtered, deduped };
@@ -2671,15 +2554,202 @@ async function ingestCursor(dbPath, wasmDir) {
2671
2554
  return { memories, sessionIds, skipped: filtered + deduped, filtered, deduped };
2672
2555
  }
2673
2556
 
2557
+ // src/detect.ts
2558
+ async function detect() {
2559
+ const home = homedir5();
2560
+ const os = platform3();
2561
+ const tools = [];
2562
+ const claudeDir = join5(home, ".claude", "projects");
2563
+ if (existsSync5(claudeDir)) {
2564
+ const sessionCount = countImportableClaudeSessions();
2565
+ tools.push({ name: "Claude Code", id: "claude", available: sessionCount > 0, path: claudeDir, sessionCount, sessionCountApproximate: true });
2566
+ } else {
2567
+ tools.push({ name: "Claude Code", id: "claude", available: false, path: claudeDir, sessionCount: 0 });
2568
+ }
2569
+ const codexConfig = join5(home, ".codex", "config.toml");
2570
+ const codexSessions = join5(home, ".codex", "sessions");
2571
+ if (existsSync5(codexConfig) || existsSync5(codexSessions)) {
2572
+ const sessionCount = countImportableCodexSessions();
2573
+ tools.push({ name: "Codex", id: "codex", available: true, path: codexConfig, sessionCount, sessionCountApproximate: true });
2574
+ } else {
2575
+ tools.push({ name: "Codex", id: "codex", available: false, path: codexConfig, sessionCount: 0 });
2576
+ }
2577
+ let cursorDbPath;
2578
+ if (os === "darwin") {
2579
+ cursorDbPath = join5(home, "Library", "Application Support", "Cursor", "User", "globalStorage", "state.vscdb");
2580
+ } else if (os === "win32") {
2581
+ cursorDbPath = join5(process.env.APPDATA || join5(home, "AppData", "Roaming"), "Cursor", "User", "globalStorage", "state.vscdb");
2582
+ } else {
2583
+ cursorDbPath = join5(home, ".config", "Cursor", "User", "globalStorage", "state.vscdb");
2584
+ }
2585
+ tools.push({
2586
+ name: "Cursor",
2587
+ id: "cursor",
2588
+ available: existsSync5(cursorDbPath),
2589
+ path: cursorDbPath,
2590
+ sessionCount: existsSync5(cursorDbPath) ? await countImportableCursorSessions(cursorDbPath) : 0,
2591
+ sessionCountApproximate: true
2592
+ });
2593
+ const windsurfDir = join5(home, ".codeium", "windsurf");
2594
+ tools.push({
2595
+ name: "Windsurf",
2596
+ id: "windsurf",
2597
+ available: existsSync5(windsurfDir),
2598
+ path: join5(windsurfDir, "mcp_config.json"),
2599
+ sessionCount: 0
2600
+ });
2601
+ let vscodePath;
2602
+ if (os === "darwin") {
2603
+ vscodePath = join5(home, "Library", "Application Support", "Code");
2604
+ } else if (os === "win32") {
2605
+ vscodePath = join5(process.env.APPDATA || join5(home, "AppData", "Roaming"), "Code");
2606
+ } else {
2607
+ vscodePath = join5(home, ".config", "Code");
2608
+ }
2609
+ tools.push({
2610
+ name: "VS Code Copilot",
2611
+ id: "vscode",
2612
+ available: existsSync5(vscodePath),
2613
+ path: join5(vscodePath, "User", "mcp.json"),
2614
+ sessionCount: 0
2615
+ });
2616
+ let clinePath;
2617
+ if (os === "darwin") {
2618
+ clinePath = join5(home, "Library", "Application Support", "Code", "User", "globalStorage", "saoudrizwan.claude-dev");
2619
+ } else if (os === "win32") {
2620
+ clinePath = join5(process.env.APPDATA || join5(home, "AppData", "Roaming"), "Code", "User", "globalStorage", "saoudrizwan.claude-dev");
2621
+ } else {
2622
+ clinePath = join5(home, ".config", "Code", "User", "globalStorage", "saoudrizwan.claude-dev");
2623
+ }
2624
+ tools.push({
2625
+ name: "Cline",
2626
+ id: "cline",
2627
+ available: existsSync5(clinePath),
2628
+ path: join5(clinePath, "settings", "cline_mcp_settings.json"),
2629
+ sessionCount: 0
2630
+ });
2631
+ const zedPath = os === "darwin" ? join5(home, ".zed") : join5(home, ".config", "zed");
2632
+ tools.push({
2633
+ name: "Zed",
2634
+ id: "zed",
2635
+ available: existsSync5(zedPath),
2636
+ path: join5(zedPath, "settings.json"),
2637
+ sessionCount: 0
2638
+ });
2639
+ const openclawDir = join5(home, ".openclaw");
2640
+ tools.push({
2641
+ name: "OpenClaw",
2642
+ id: "openclaw",
2643
+ available: existsSync5(openclawDir),
2644
+ path: join5(openclawDir, "openclaw.json"),
2645
+ sessionCount: 0
2646
+ });
2647
+ const antigravityDir = join5(home, ".gemini", "antigravity");
2648
+ const antigravityConvDir = join5(antigravityDir, "conversations");
2649
+ let antigravityCount = 0;
2650
+ if (existsSync5(antigravityConvDir)) {
2651
+ try {
2652
+ antigravityCount = readdirSync3(antigravityConvDir).filter((f) => f.endsWith(".pb")).length;
2653
+ } catch {}
2654
+ }
2655
+ tools.push({
2656
+ name: "Antigravity",
2657
+ id: "antigravity",
2658
+ available: existsSync5(antigravityDir),
2659
+ path: join5(antigravityDir, "mcp_config.json"),
2660
+ sessionCount: antigravityCount
2661
+ });
2662
+ return tools;
2663
+ }
2664
+
2665
+ // src/auth.ts
2666
+ import { execSync } from "node:child_process";
2667
+ import { platform as platform4 } from "node:os";
2668
+ var API_URL = "https://conare.ai";
2669
+ async function browserAuth() {
2670
+ const stateBytes = new Uint8Array(16);
2671
+ crypto.getRandomValues(stateBytes);
2672
+ const state = Array.from(stateBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
2673
+ const sessionRes = await fetch(`${API_URL}/api/auth/cli-session`, {
2674
+ method: "POST",
2675
+ headers: { "Content-Type": "application/json" },
2676
+ body: JSON.stringify({ state })
2677
+ });
2678
+ if (!sessionRes.ok) {
2679
+ throw new Error(`Failed to create auth session: HTTP ${sessionRes.status}`);
2680
+ }
2681
+ const { code, expiresAt } = await sessionRes.json();
2682
+ const authUrl = `${API_URL}/cli-auth?code=${code}&state=${state}`;
2683
+ const opened = openBrowser(authUrl);
2684
+ if (!opened) {
2685
+ console.log("");
2686
+ console.log(" Open this URL in your browser to sign in:");
2687
+ console.log("");
2688
+ console.log(` ${authUrl}`);
2689
+ console.log("");
2690
+ }
2691
+ const timeout = Math.max(expiresAt - Date.now(), 0);
2692
+ const deadline = Date.now() + timeout;
2693
+ while (Date.now() < deadline) {
2694
+ await sleep(2000);
2695
+ const exchangeRes = await fetch(`${API_URL}/api/auth/cli-exchange`, {
2696
+ method: "POST",
2697
+ headers: { "Content-Type": "application/json" },
2698
+ body: JSON.stringify({ code, state })
2699
+ });
2700
+ if (exchangeRes.status === 202) {
2701
+ continue;
2702
+ }
2703
+ if (exchangeRes.ok) {
2704
+ const data = await exchangeRes.json();
2705
+ return data.apiKey;
2706
+ }
2707
+ if (exchangeRes.status === 410) {
2708
+ throw new Error("Authentication code was already used. Please try again.");
2709
+ }
2710
+ if (exchangeRes.status === 404) {
2711
+ throw new Error("Authentication session expired. Please try again.");
2712
+ }
2713
+ throw new Error(`Authentication failed: HTTP ${exchangeRes.status}`);
2714
+ }
2715
+ throw new Error("Authentication timed out. Please try again.");
2716
+ }
2717
+ function openBrowser(url) {
2718
+ try {
2719
+ const os = platform4();
2720
+ if (os === "darwin") {
2721
+ execSync(`open "${url}"`, { stdio: "ignore" });
2722
+ } else if (os === "win32") {
2723
+ execSync(`start "" "${url}"`, { stdio: "ignore" });
2724
+ } else {
2725
+ try {
2726
+ execSync(`xdg-open "${url}"`, { stdio: "ignore" });
2727
+ } catch {
2728
+ try {
2729
+ execSync(`wslview "${url}"`, { stdio: "ignore" });
2730
+ } catch {
2731
+ return false;
2732
+ }
2733
+ }
2734
+ }
2735
+ return true;
2736
+ } catch {
2737
+ return false;
2738
+ }
2739
+ }
2740
+ function sleep(ms) {
2741
+ return new Promise((resolve) => setTimeout(resolve, ms));
2742
+ }
2743
+
2674
2744
  // src/index.ts
2675
2745
  init_codebase();
2676
2746
  init_shared();
2677
2747
  init_api();
2678
2748
 
2679
2749
  // src/configure.ts
2680
- import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync7, writeFileSync as writeFileSync2, symlinkSync, readlinkSync, rmSync } from "node:fs";
2681
- import { dirname, join as join7 } from "node:path";
2682
- import { homedir as homedir5, platform as platform5 } from "node:os";
2750
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync as writeFileSync2, symlinkSync, readlinkSync, rmSync } from "node:fs";
2751
+ import { dirname as dirname2, join as join7 } from "node:path";
2752
+ import { homedir as homedir6, platform as platform5 } from "node:os";
2683
2753
  import { spawnSync } from "node:child_process";
2684
2754
  var CONARE_URL = "https://conare.ai";
2685
2755
  var SERVER_NAME = "conare";
@@ -2696,13 +2766,13 @@ var MCP_TARGETS = [
2696
2766
  ];
2697
2767
  function readJsonFile(path) {
2698
2768
  try {
2699
- return JSON.parse(readFileSync7(path, "utf-8"));
2769
+ return JSON.parse(readFileSync6(path, "utf-8"));
2700
2770
  } catch {
2701
2771
  return {};
2702
2772
  }
2703
2773
  }
2704
2774
  function writeJsonFile(path, data) {
2705
- mkdirSync2(dirname(path), { recursive: true });
2775
+ mkdirSync2(dirname2(path), { recursive: true });
2706
2776
  writeFileSync2(path, JSON.stringify(data, null, 2) + `
2707
2777
  `);
2708
2778
  }
@@ -2740,7 +2810,7 @@ function configureClaude(apiKey) {
2740
2810
  }).status === 0) {
2741
2811
  return "\x1B[32m✓\x1B[0m Claude Code";
2742
2812
  }
2743
- const claudeConfigPath = join7(homedir5(), ".claude.json");
2813
+ const claudeConfigPath = join7(homedir6(), ".claude.json");
2744
2814
  const config = readJsonFile(claudeConfigPath);
2745
2815
  if (!config.mcpServers || typeof config.mcpServers !== "object") {
2746
2816
  config.mcpServers = {};
@@ -2750,7 +2820,7 @@ function configureClaude(apiKey) {
2750
2820
  return "\x1B[32m✓\x1B[0m Claude Code (json fallback)";
2751
2821
  }
2752
2822
  function configureCodex(apiKey) {
2753
- const configPath = join7(homedir5(), ".codex", "config.toml");
2823
+ const configPath = join7(homedir6(), ".codex", "config.toml");
2754
2824
  if (spawnSync("codex", ["mcp", "add", SERVER_NAME, "--url", `${CONARE_URL}/mcp`, "--header", `Authorization: Bearer ${apiKey}`], {
2755
2825
  stdio: "ignore",
2756
2826
  shell: platform5() === "win32"
@@ -2759,7 +2829,7 @@ function configureCodex(apiKey) {
2759
2829
  }
2760
2830
  let toml = "";
2761
2831
  try {
2762
- toml = readFileSync7(configPath, "utf-8");
2832
+ toml = readFileSync6(configPath, "utf-8");
2763
2833
  } catch {}
2764
2834
  const sectionHeader = `[mcp_servers.${SERVER_NAME}]`;
2765
2835
  const newSection = [
@@ -2780,11 +2850,11 @@ function configureCodex(apiKey) {
2780
2850
  ${newSection}
2781
2851
  ` : `${newSection}
2782
2852
  `;
2783
- mkdirSync2(dirname(configPath), { recursive: true });
2853
+ mkdirSync2(dirname2(configPath), { recursive: true });
2784
2854
  writeFileSync2(configPath, result);
2785
- const oldMcpJson = join7(homedir5(), ".codex", "mcp.json");
2855
+ const oldMcpJson = join7(homedir6(), ".codex", "mcp.json");
2786
2856
  try {
2787
- if (existsSync6(oldMcpJson)) {
2857
+ if (existsSync7(oldMcpJson)) {
2788
2858
  const old = readJsonFile(oldMcpJson);
2789
2859
  const servers = old.mcpServers;
2790
2860
  if (servers && (("conare" in servers) || ("conare-memory" in servers))) {
@@ -2801,7 +2871,7 @@ ${newSection}
2801
2871
  return "\x1B[32m✓\x1B[0m Codex";
2802
2872
  }
2803
2873
  function configureCursor(apiKey) {
2804
- const configPath = join7(homedir5(), ".cursor", "mcp.json");
2874
+ const configPath = join7(homedir6(), ".cursor", "mcp.json");
2805
2875
  const config = readJsonFile(configPath);
2806
2876
  if (!config.mcpServers || typeof config.mcpServers !== "object") {
2807
2877
  config.mcpServers = {};
@@ -2814,7 +2884,7 @@ function configureCursor(apiKey) {
2814
2884
  return "\x1B[32m✓\x1B[0m Cursor";
2815
2885
  }
2816
2886
  function configureWindsurf(apiKey) {
2817
- const configPath = join7(homedir5(), ".codeium", "windsurf", "mcp_config.json");
2887
+ const configPath = join7(homedir6(), ".codeium", "windsurf", "mcp_config.json");
2818
2888
  const config = readJsonFile(configPath);
2819
2889
  if (!config.mcpServers || typeof config.mcpServers !== "object") {
2820
2890
  config.mcpServers = {};
@@ -2830,11 +2900,11 @@ function configureVscode(apiKey) {
2830
2900
  const os = platform5();
2831
2901
  let configPath;
2832
2902
  if (os === "darwin") {
2833
- configPath = join7(homedir5(), "Library", "Application Support", "Code", "User", "mcp.json");
2903
+ configPath = join7(homedir6(), "Library", "Application Support", "Code", "User", "mcp.json");
2834
2904
  } else if (os === "win32") {
2835
- configPath = join7(process.env.APPDATA || join7(homedir5(), "AppData", "Roaming"), "Code", "User", "mcp.json");
2905
+ configPath = join7(process.env.APPDATA || join7(homedir6(), "AppData", "Roaming"), "Code", "User", "mcp.json");
2836
2906
  } else {
2837
- configPath = join7(homedir5(), ".config", "Code", "User", "mcp.json");
2907
+ configPath = join7(homedir6(), ".config", "Code", "User", "mcp.json");
2838
2908
  }
2839
2909
  const config = readJsonFile(configPath);
2840
2910
  if (!config.servers || typeof config.servers !== "object") {
@@ -2852,11 +2922,11 @@ function configureCline(apiKey) {
2852
2922
  const os = platform5();
2853
2923
  let configPath;
2854
2924
  if (os === "darwin") {
2855
- configPath = join7(homedir5(), "Library", "Application Support", "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json");
2925
+ configPath = join7(homedir6(), "Library", "Application Support", "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json");
2856
2926
  } else if (os === "win32") {
2857
- configPath = join7(process.env.APPDATA || join7(homedir5(), "AppData", "Roaming"), "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json");
2927
+ configPath = join7(process.env.APPDATA || join7(homedir6(), "AppData", "Roaming"), "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json");
2858
2928
  } else {
2859
- configPath = join7(homedir5(), ".config", "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json");
2929
+ configPath = join7(homedir6(), ".config", "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json");
2860
2930
  }
2861
2931
  const config = readJsonFile(configPath);
2862
2932
  if (!config.mcpServers || typeof config.mcpServers !== "object") {
@@ -2874,9 +2944,9 @@ function configureZed(apiKey) {
2874
2944
  const os = platform5();
2875
2945
  let configPath;
2876
2946
  if (os === "darwin") {
2877
- configPath = join7(homedir5(), ".zed", "settings.json");
2947
+ configPath = join7(homedir6(), ".zed", "settings.json");
2878
2948
  } else {
2879
- configPath = join7(homedir5(), ".config", "zed", "settings.json");
2949
+ configPath = join7(homedir6(), ".config", "zed", "settings.json");
2880
2950
  }
2881
2951
  const config = readJsonFile(configPath);
2882
2952
  if (!config.context_servers || typeof config.context_servers !== "object") {
@@ -2897,7 +2967,7 @@ function configureZed(apiKey) {
2897
2967
  return "\x1B[32m✓\x1B[0m Zed";
2898
2968
  }
2899
2969
  function configureOpenclaw(apiKey) {
2900
- const configPath = join7(homedir5(), ".openclaw", "openclaw.json");
2970
+ const configPath = join7(homedir6(), ".openclaw", "openclaw.json");
2901
2971
  const config = readJsonFile(configPath);
2902
2972
  if (!config.mcpServers || typeof config.mcpServers !== "object") {
2903
2973
  config.mcpServers = {};
@@ -2911,7 +2981,7 @@ function configureOpenclaw(apiKey) {
2911
2981
  return "\x1B[32m✓\x1B[0m OpenClaw";
2912
2982
  }
2913
2983
  function configureAntigravity(apiKey) {
2914
- const configPath = join7(homedir5(), ".gemini", "antigravity", "mcp_config.json");
2984
+ const configPath = join7(homedir6(), ".gemini", "antigravity", "mcp_config.json");
2915
2985
  const config = readJsonFile(configPath);
2916
2986
  if (!config.mcpServers || typeof config.mcpServers !== "object") {
2917
2987
  config.mcpServers = {};
@@ -3042,14 +3112,14 @@ The wizard handles everything: account creation, API key, MCP configuration, bac
3042
3112
  For manual setup, visit [conare.ai](https://conare.ai).
3043
3113
  `;
3044
3114
  function installSkill() {
3045
- const skillDir = join7(homedir5(), ".agents", "skills", "conare");
3115
+ const skillDir = join7(homedir6(), ".agents", "skills", "conare");
3046
3116
  mkdirSync2(skillDir, { recursive: true });
3047
3117
  writeFileSync2(join7(skillDir, "SKILL.md"), SKILL_MD);
3048
- const claudeSkillsDir = join7(homedir5(), ".claude", "skills");
3118
+ const claudeSkillsDir = join7(homedir6(), ".claude", "skills");
3049
3119
  const claudeSkillDir = join7(claudeSkillsDir, "conare");
3050
3120
  try {
3051
- if (existsSync6(claudeSkillsDir)) {
3052
- if (existsSync6(claudeSkillDir)) {
3121
+ if (existsSync7(claudeSkillsDir)) {
3122
+ if (existsSync7(claudeSkillDir)) {
3053
3123
  try {
3054
3124
  if (readlinkSync(claudeSkillDir) === skillDir)
3055
3125
  return "\x1B[32m✓\x1B[0m Agent Skill";
@@ -3080,16 +3150,16 @@ function configureMcp(apiKey, targets = ["claude", "codex"]) {
3080
3150
  }
3081
3151
 
3082
3152
  // src/config.ts
3083
- import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync3 } from "node:fs";
3153
+ import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync3 } from "node:fs";
3084
3154
  import { join as join8 } from "node:path";
3085
- import { homedir as homedir6 } from "node:os";
3086
- var CONFIG_DIR = join8(homedir6(), ".conare");
3155
+ import { homedir as homedir7 } from "node:os";
3156
+ var CONFIG_DIR = join8(homedir7(), ".conare");
3087
3157
  var CONFIG_PATH = join8(CONFIG_DIR, "config.json");
3088
3158
  function readConfig() {
3089
3159
  try {
3090
- if (!existsSync7(CONFIG_PATH))
3160
+ if (!existsSync8(CONFIG_PATH))
3091
3161
  return {};
3092
- return JSON.parse(readFileSync8(CONFIG_PATH, "utf-8"));
3162
+ return JSON.parse(readFileSync7(CONFIG_PATH, "utf-8"));
3093
3163
  } catch {
3094
3164
  return {};
3095
3165
  }
@@ -3109,16 +3179,16 @@ function getSavedApiKey() {
3109
3179
  }
3110
3180
 
3111
3181
  // src/sync.ts
3112
- import { existsSync as existsSync8, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4, unlinkSync, readFileSync as readFileSync9, chmodSync, cpSync, rmSync as rmSync2, symlinkSync as symlinkSync2, readlinkSync as readlinkSync2, appendFileSync } from "node:fs";
3113
- import { join as join9, dirname as dirname2 } from "node:path";
3114
- import { homedir as homedir7, platform as platform6 } from "node:os";
3182
+ import { existsSync as existsSync9, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4, unlinkSync, readFileSync as readFileSync8, chmodSync, cpSync, rmSync as rmSync2, symlinkSync as symlinkSync2, readlinkSync as readlinkSync2, appendFileSync } from "node:fs";
3183
+ import { join as join9, dirname as dirname3 } from "node:path";
3184
+ import { homedir as homedir8, platform as platform6 } from "node:os";
3115
3185
  import { execSync as execSync3 } from "node:child_process";
3116
- var CONARE_DIR = join9(homedir7(), ".conare");
3186
+ var CONARE_DIR = join9(homedir8(), ".conare");
3117
3187
  var BIN_DIR = join9(CONARE_DIR, "bin");
3118
3188
  var CONFIG_PATH2 = join9(CONARE_DIR, "config.json");
3119
3189
  var PLIST_LABEL = "ai.conare.ingest";
3120
- var PLIST_PATH = join9(homedir7(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
3121
- var SYSTEMD_DIR = join9(homedir7(), ".config", "systemd", "user");
3190
+ var PLIST_PATH = join9(homedir8(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
3191
+ var SYSTEMD_DIR = join9(homedir8(), ".config", "systemd", "user");
3122
3192
  var SYSTEMD_SERVICE = join9(SYSTEMD_DIR, "conare-sync.service");
3123
3193
  var SYSTEMD_TIMER = join9(SYSTEMD_DIR, "conare-sync.timer");
3124
3194
  var TASK_NAME = "ConareMemorySync";
@@ -3263,7 +3333,7 @@ function persistBinary(apiKey) {
3263
3333
  throw new Error("Could not locate CLI bundle. Run from an installed conare package.");
3264
3334
  }
3265
3335
  const dest = join9(BIN_DIR, "conare-ingest.mjs");
3266
- const content = readFileSync9(cliEntry, "utf-8");
3336
+ const content = readFileSync8(cliEntry, "utf-8");
3267
3337
  writeFileSync4(dest, content);
3268
3338
  const sqlJsDir = findSqlJs();
3269
3339
  if (sqlJsDir) {
@@ -3286,17 +3356,17 @@ function persistBinary(apiKey) {
3286
3356
  `, { mode: 384 });
3287
3357
  }
3288
3358
  function isValidJsBundle(path) {
3289
- if (!existsSync8(path))
3359
+ if (!existsSync9(path))
3290
3360
  return false;
3291
3361
  if (path.endsWith(".ts") || path.endsWith(".tsx"))
3292
3362
  return false;
3293
- const head = readFileSync9(path, "utf-8").slice(0, 2000);
3363
+ const head = readFileSync8(path, "utf-8").slice(0, 2000);
3294
3364
  if (/\btype\s+\{/.test(head) || /,\s*type\s+\w+/.test(head))
3295
3365
  return false;
3296
3366
  return true;
3297
3367
  }
3298
3368
  function findCliBundle() {
3299
- const dir = dirname2(new URL(import.meta.url).pathname);
3369
+ const dir = dirname3(new URL(import.meta.url).pathname);
3300
3370
  const distCandidates = [
3301
3371
  join9(dir, "index.js"),
3302
3372
  join9(dir, "..", "dist", "index.js")
@@ -3313,11 +3383,11 @@ function findCliBundle() {
3313
3383
  function findSqlJs() {
3314
3384
  const candidates = [
3315
3385
  join9(process.cwd(), "node_modules", "sql.js"),
3316
- join9(dirname2(new URL(import.meta.url).pathname), "..", "node_modules", "sql.js"),
3317
- join9(dirname2(new URL(import.meta.url).pathname), "..", "..", "node_modules", "sql.js")
3386
+ join9(dirname3(new URL(import.meta.url).pathname), "..", "node_modules", "sql.js"),
3387
+ join9(dirname3(new URL(import.meta.url).pathname), "..", "..", "node_modules", "sql.js")
3318
3388
  ];
3319
3389
  for (const c of candidates) {
3320
- if (existsSync8(c))
3390
+ if (existsSync9(c))
3321
3391
  return c;
3322
3392
  }
3323
3393
  return null;
@@ -3326,7 +3396,7 @@ function cleanupOldLaunchAgent() {
3326
3396
  try {
3327
3397
  execSync3(`launchctl bootout gui/${uid()} "${PLIST_PATH}" 2>/dev/null`, { stdio: "ignore" });
3328
3398
  } catch {}
3329
- if (existsSync8(PLIST_PATH)) {
3399
+ if (existsSync9(PLIST_PATH)) {
3330
3400
  unlinkSync(PLIST_PATH);
3331
3401
  }
3332
3402
  }
@@ -3355,7 +3425,7 @@ function clampCronInterval(intervalMinutes) {
3355
3425
  }
3356
3426
  function setupCron(intervalMinutes) {
3357
3427
  const clamped = clampCronInterval(intervalMinutes);
3358
- const cronCmd = `"${homedir7()}/.conare/bin/run.sh"`;
3428
+ const cronCmd = `"${homedir8()}/.conare/bin/run.sh"`;
3359
3429
  const cronLine = `*/${clamped} * * * * ${cronCmd} # conare-sync`;
3360
3430
  try {
3361
3431
  const existing = execSync3("crontab -l 2>/dev/null", { encoding: "utf-8" });
@@ -3398,13 +3468,13 @@ function runSyncNow() {
3398
3468
  try {
3399
3469
  if (os === "win32") {
3400
3470
  const runCmd = join9(BIN_DIR, "run.cmd");
3401
- if (existsSync8(runCmd)) {
3471
+ if (existsSync9(runCmd)) {
3402
3472
  execSync3(`"${runCmd}"`, { stdio: "ignore", timeout: 60000 });
3403
3473
  return true;
3404
3474
  }
3405
3475
  } else {
3406
3476
  const runSh = join9(BIN_DIR, "run.sh");
3407
- if (existsSync8(runSh)) {
3477
+ if (existsSync9(runSh)) {
3408
3478
  execSync3(`/bin/bash "${runSh}"`, { stdio: "ignore", timeout: 60000 });
3409
3479
  return true;
3410
3480
  }
@@ -3458,7 +3528,7 @@ exec "$NODE" "$CONARE_DIR/bin/conare-ingest.mjs" "$@"
3458
3528
  chmodSync(wrapper, 493);
3459
3529
  const symlinkTarget = "/usr/local/bin/conare";
3460
3530
  try {
3461
- if (existsSync8(symlinkTarget)) {
3531
+ if (existsSync9(symlinkTarget)) {
3462
3532
  try {
3463
3533
  const existing = readlinkSync2(symlinkTarget);
3464
3534
  if (existing === wrapper)
@@ -3476,7 +3546,7 @@ exec "$NODE" "$CONARE_DIR/bin/conare-ingest.mjs" "$@"
3476
3546
  const shellProfile = getShellProfile();
3477
3547
  if (shellProfile) {
3478
3548
  try {
3479
- const profileContent = existsSync8(shellProfile) ? readFileSync9(shellProfile, "utf-8") : "";
3549
+ const profileContent = existsSync9(shellProfile) ? readFileSync8(shellProfile, "utf-8") : "";
3480
3550
  const exportLine = `export PATH="$HOME/.conare/bin:$PATH"`;
3481
3551
  if (!profileContent.includes(".conare/bin")) {
3482
3552
  appendFileSync(shellProfile, `
@@ -3494,19 +3564,19 @@ ${exportLine}
3494
3564
  }
3495
3565
  }
3496
3566
  function getShellProfile() {
3497
- const home = homedir7();
3567
+ const home = homedir8();
3498
3568
  const shell = process.env.SHELL || "";
3499
3569
  if (shell.includes("zsh"))
3500
3570
  return join9(home, ".zshrc");
3501
3571
  if (shell.includes("bash")) {
3502
3572
  const profile = join9(home, ".bash_profile");
3503
- if (platform6() === "darwin" && existsSync8(profile))
3573
+ if (platform6() === "darwin" && existsSync9(profile))
3504
3574
  return profile;
3505
3575
  return join9(home, ".bashrc");
3506
3576
  }
3507
- if (existsSync8(join9(home, ".zshrc")))
3577
+ if (existsSync9(join9(home, ".zshrc")))
3508
3578
  return join9(home, ".zshrc");
3509
- if (existsSync8(join9(home, ".bashrc")))
3579
+ if (existsSync9(join9(home, ".bashrc")))
3510
3580
  return join9(home, ".bashrc");
3511
3581
  return null;
3512
3582
  }
@@ -3576,9 +3646,9 @@ function uninstallSync() {
3576
3646
  try {
3577
3647
  execSync3("systemctl --user disable --now conare-sync.timer 2>/dev/null", { stdio: "ignore" });
3578
3648
  } catch {}
3579
- if (existsSync8(SYSTEMD_SERVICE))
3649
+ if (existsSync9(SYSTEMD_SERVICE))
3580
3650
  unlinkSync(SYSTEMD_SERVICE);
3581
- if (existsSync8(SYSTEMD_TIMER))
3651
+ if (existsSync9(SYSTEMD_TIMER))
3582
3652
  unlinkSync(SYSTEMD_TIMER);
3583
3653
  try {
3584
3654
  execSync3("systemctl --user daemon-reload", { stdio: "ignore" });
@@ -3589,15 +3659,15 @@ function uninstallSync() {
3589
3659
  }
3590
3660
  }
3591
3661
  const configPath = join9(CONARE_DIR, "config.json");
3592
- if (existsSync8(configPath))
3662
+ if (existsSync9(configPath))
3593
3663
  unlinkSync(configPath);
3594
3664
  const lockDir = join9(CONARE_DIR, "sync.lock.d");
3595
- if (existsSync8(lockDir))
3665
+ if (existsSync9(lockDir))
3596
3666
  rmSync2(lockDir, { recursive: true, force: true });
3597
3667
  const lockFile = join9(CONARE_DIR, "sync.lock");
3598
- if (existsSync8(lockFile))
3668
+ if (existsSync9(lockFile))
3599
3669
  unlinkSync(lockFile);
3600
- if (existsSync8(BIN_DIR)) {
3670
+ if (existsSync9(BIN_DIR)) {
3601
3671
  rmSync2(BIN_DIR, { recursive: true, force: true });
3602
3672
  messages.push("Removed ~/.conare/bin/");
3603
3673
  }
@@ -3677,6 +3747,9 @@ function renderSourceBreakdown(memories) {
3677
3747
  }
3678
3748
  return [...counts.entries()].map(([tag, count]) => `${CHAT_CONTAINER_LABELS[tag] || tag}: ${count}`).join(", ");
3679
3749
  }
3750
+ function formatSessionCount(count, approximate) {
3751
+ return `${approximate ? "~" : ""}${count} sessions`;
3752
+ }
3680
3753
  function parseArgs() {
3681
3754
  const args = process.argv.slice(2);
3682
3755
  let key = "";
@@ -3829,12 +3902,12 @@ async function runInstall() {
3829
3902
  console.log("");
3830
3903
  }
3831
3904
  async function runLogout() {
3832
- const { unlinkSync: unlinkSync2, existsSync: existsSync10 } = await import("node:fs");
3905
+ const { unlinkSync: unlinkSync2, existsSync: existsSync11 } = await import("node:fs");
3833
3906
  const { join: join11 } = await import("node:path");
3834
- const { homedir: homedir8 } = await import("node:os");
3907
+ const { homedir: homedir9 } = await import("node:os");
3835
3908
  const messages = uninstallSync();
3836
- const manifestPath = join11(homedir8(), ".conare", "ingested.json");
3837
- if (existsSync10(manifestPath)) {
3909
+ const manifestPath = join11(homedir9(), ".conare", "ingested.json");
3910
+ if (existsSync11(manifestPath)) {
3838
3911
  unlinkSync2(manifestPath);
3839
3912
  messages.push("Removed local index history");
3840
3913
  }
@@ -3856,8 +3929,8 @@ async function main() {
3856
3929
  let configFileKey;
3857
3930
  if (opts.configFile) {
3858
3931
  try {
3859
- const { readFileSync: readFileSync10 } = await import("node:fs");
3860
- const raw = JSON.parse(readFileSync10(opts.configFile, "utf-8"));
3932
+ const { readFileSync: readFileSync9 } = await import("node:fs");
3933
+ const raw = JSON.parse(readFileSync9(opts.configFile, "utf-8"));
3861
3934
  configFileKey = raw.apiKey || raw.key;
3862
3935
  if (!configFileKey) {
3863
3936
  console.error(`Error: no apiKey/key found in ${opts.configFile}`);
@@ -3884,7 +3957,8 @@ async function main() {
3884
3957
  label: target.label,
3885
3958
  available: true,
3886
3959
  recommended: target.defaultSelected,
3887
- detectedCount: undefined
3960
+ detectedCount: undefined,
3961
+ detectedCountApproximate: undefined
3888
3962
  }));
3889
3963
  let interactiveMode = false;
3890
3964
  if (shouldRunInteractive) {
@@ -3896,7 +3970,8 @@ async function main() {
3896
3970
  label: target.label,
3897
3971
  available: detected?.available,
3898
3972
  recommended: target.defaultSelected && detected?.available !== false,
3899
- detectedCount: detected?.sessionCount
3973
+ detectedCount: detected?.sessionCount,
3974
+ detectedCountApproximate: detected?.sessionCountApproximate
3900
3975
  };
3901
3976
  });
3902
3977
  startSetup();
@@ -3976,7 +4051,7 @@ async function main() {
3976
4051
  log("");
3977
4052
  }
3978
4053
  }
3979
- if (!opts.wasmDir && existsSync9(join10(process.cwd(), "node_modules", "sql.js"))) {
4054
+ if (!opts.wasmDir && existsSync10(join10(process.cwd(), "node_modules", "sql.js"))) {
3980
4055
  opts.wasmDir = join10(process.cwd(), "node_modules");
3981
4056
  }
3982
4057
  if (effectiveConfigOnly) {
@@ -4099,7 +4174,7 @@ Nothing new to index.`);
4099
4174
  log("Detected AI tools:");
4100
4175
  for (const t of tools) {
4101
4176
  if (t.available) {
4102
- log(` + ${t.name}${t.sessionCount || t.sessionCount === 0 ? ` — ${t.sessionCount} sessions` : ""}`);
4177
+ log(` + ${t.name}${t.sessionCount || t.sessionCount === 0 ? ` — ${formatSessionCount(t.sessionCount, t.sessionCountApproximate)}` : ""}`);
4103
4178
  } else {
4104
4179
  log(` - ${t.name} (not found)`);
4105
4180
  }