conare 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +144 -129
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -153,6 +153,7 @@ import { join as join9 } from "node:path";
|
|
|
153
153
|
|
|
154
154
|
// src/detect.ts
|
|
155
155
|
import { existsSync, readdirSync } from "node:fs";
|
|
156
|
+
import { spawnSync } from "node:child_process";
|
|
156
157
|
import { join } from "node:path";
|
|
157
158
|
import { homedir, platform } from "node:os";
|
|
158
159
|
function countJsonlFiles(dir) {
|
|
@@ -168,6 +169,49 @@ function countJsonlFiles(dir) {
|
|
|
168
169
|
} catch {}
|
|
169
170
|
return count;
|
|
170
171
|
}
|
|
172
|
+
function countCursorSessions(dbPath) {
|
|
173
|
+
try {
|
|
174
|
+
const result = spawnSync("sqlite3", [
|
|
175
|
+
dbPath,
|
|
176
|
+
`
|
|
177
|
+
WITH composer_rows AS (
|
|
178
|
+
SELECT substr(key, 14) AS composer_id, value AS composer_json
|
|
179
|
+
FROM cursorDiskKV
|
|
180
|
+
WHERE key LIKE 'composerData:%'
|
|
181
|
+
),
|
|
182
|
+
headers AS (
|
|
183
|
+
SELECT
|
|
184
|
+
composer_id,
|
|
185
|
+
json_extract(j.value, '$.bubbleId') AS bubble_id,
|
|
186
|
+
json_extract(j.value, '$.type') AS type
|
|
187
|
+
FROM composer_rows, json_each(json_extract(composer_json, '$.fullConversationHeadersOnly')) AS j
|
|
188
|
+
),
|
|
189
|
+
messages AS (
|
|
190
|
+
SELECT h.composer_id, h.type
|
|
191
|
+
FROM headers h
|
|
192
|
+
JOIN cursorDiskKV kv
|
|
193
|
+
ON kv.key = 'bubbleId:' || h.composer_id || ':' || h.bubble_id
|
|
194
|
+
WHERE h.type IN (1, 2)
|
|
195
|
+
AND length(COALESCE(json_extract(kv.value, '$.text'), '')) >= 50
|
|
196
|
+
)
|
|
197
|
+
SELECT count(*)
|
|
198
|
+
FROM (
|
|
199
|
+
SELECT composer_id
|
|
200
|
+
FROM messages
|
|
201
|
+
GROUP BY composer_id
|
|
202
|
+
HAVING SUM(CASE WHEN type = 1 THEN 1 ELSE 0 END) > 0
|
|
203
|
+
AND SUM(CASE WHEN type = 2 THEN 1 ELSE 0 END) > 0
|
|
204
|
+
);
|
|
205
|
+
`.trim()
|
|
206
|
+
], { encoding: "utf-8" });
|
|
207
|
+
if (result.status !== 0)
|
|
208
|
+
return 0;
|
|
209
|
+
const count = Number.parseInt(result.stdout.trim(), 10);
|
|
210
|
+
return Number.isFinite(count) ? count : 0;
|
|
211
|
+
} catch {
|
|
212
|
+
return 0;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
171
215
|
function detect() {
|
|
172
216
|
const home = homedir();
|
|
173
217
|
const tools = [];
|
|
@@ -225,7 +269,7 @@ function detect() {
|
|
|
225
269
|
name: "Cursor",
|
|
226
270
|
available: existsSync(cursorDbPath),
|
|
227
271
|
path: cursorDbPath,
|
|
228
|
-
sessionCount: 0
|
|
272
|
+
sessionCount: existsSync(cursorDbPath) ? countCursorSessions(cursorDbPath) : 0
|
|
229
273
|
});
|
|
230
274
|
return tools;
|
|
231
275
|
}
|
|
@@ -1029,7 +1073,7 @@ async function uploadBulk(apiKey, memories, onProgress) {
|
|
|
1029
1073
|
import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1030
1074
|
import { dirname, join as join7 } from "node:path";
|
|
1031
1075
|
import { homedir as homedir5 } from "node:os";
|
|
1032
|
-
import { spawnSync } from "node:child_process";
|
|
1076
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
1033
1077
|
var CONARE_URL = "https://mcp.conare.ai";
|
|
1034
1078
|
var SERVER_NAME = "conare-memory";
|
|
1035
1079
|
var MCP_TARGETS = [
|
|
@@ -1069,7 +1113,7 @@ function upsertMcpServer(path, apiKey) {
|
|
|
1069
1113
|
function configureClaude(apiKey) {
|
|
1070
1114
|
const claudeConfigPath = join7(homedir5(), ".claude.json");
|
|
1071
1115
|
const claudeMcpPath = join7(homedir5(), ".claude", "mcp.json");
|
|
1072
|
-
if (
|
|
1116
|
+
if (spawnSync2("claude", ["mcp", "add-json", SERVER_NAME, "--scope", "user", JSON.stringify(getServerConfig(apiKey))], {
|
|
1073
1117
|
stdio: "ignore"
|
|
1074
1118
|
}).status === 0) {
|
|
1075
1119
|
return "Claude Code configured via `claude mcp add-json`";
|
|
@@ -1538,24 +1582,6 @@ class MD extends x {
|
|
|
1538
1582
|
return this.value.replaceAll(/./g, this._mask);
|
|
1539
1583
|
}
|
|
1540
1584
|
}
|
|
1541
|
-
class RD extends x {
|
|
1542
|
-
get valueWithCursor() {
|
|
1543
|
-
if (this.state === "submit")
|
|
1544
|
-
return this.value;
|
|
1545
|
-
if (this.cursor >= this.value.length)
|
|
1546
|
-
return `${this.value}█`;
|
|
1547
|
-
const u = this.value.slice(0, this.cursor), [t, ...F] = this.value.slice(this.cursor);
|
|
1548
|
-
return `${u}${import_picocolors.default.inverse(t)}${F.join("")}`;
|
|
1549
|
-
}
|
|
1550
|
-
get cursor() {
|
|
1551
|
-
return this._cursor;
|
|
1552
|
-
}
|
|
1553
|
-
constructor(u) {
|
|
1554
|
-
super(u), this.on("finalize", () => {
|
|
1555
|
-
this.value || (this.value = u.defaultValue);
|
|
1556
|
-
});
|
|
1557
|
-
}
|
|
1558
|
-
}
|
|
1559
1585
|
|
|
1560
1586
|
// node_modules/@clack/prompts/dist/index.mjs
|
|
1561
1587
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
@@ -1610,27 +1636,6 @@ var G2 = (t) => {
|
|
|
1610
1636
|
return j2 || E ? import_picocolors2.default.dim("...") : i(p2, v2 + l2 === n);
|
|
1611
1637
|
});
|
|
1612
1638
|
};
|
|
1613
|
-
var he = (t) => new RD({ validate: t.validate, placeholder: t.placeholder, defaultValue: t.defaultValue, initialValue: t.initialValue, render() {
|
|
1614
|
-
const n = `${import_picocolors2.default.gray(o)}
|
|
1615
|
-
${b2(this.state)} ${t.message}
|
|
1616
|
-
`, r2 = t.placeholder ? import_picocolors2.default.inverse(t.placeholder[0]) + import_picocolors2.default.dim(t.placeholder.slice(1)) : import_picocolors2.default.inverse(import_picocolors2.default.hidden("_")), i = this.value ? this.valueWithCursor : r2;
|
|
1617
|
-
switch (this.state) {
|
|
1618
|
-
case "error":
|
|
1619
|
-
return `${n.trim()}
|
|
1620
|
-
${import_picocolors2.default.yellow(o)} ${i}
|
|
1621
|
-
${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(this.error)}
|
|
1622
|
-
`;
|
|
1623
|
-
case "submit":
|
|
1624
|
-
return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(this.value || t.placeholder)}`;
|
|
1625
|
-
case "cancel":
|
|
1626
|
-
return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(this.value ?? ""))}${this.value?.trim() ? `
|
|
1627
|
-
${import_picocolors2.default.gray(o)}` : ""}`;
|
|
1628
|
-
default:
|
|
1629
|
-
return `${n}${import_picocolors2.default.cyan(o)} ${i}
|
|
1630
|
-
${import_picocolors2.default.cyan(d2)}
|
|
1631
|
-
`;
|
|
1632
|
-
}
|
|
1633
|
-
} }).prompt();
|
|
1634
1639
|
var ge = (t) => new MD({ validate: t.validate, mask: t.mask ?? $e, render() {
|
|
1635
1640
|
const n = `${import_picocolors2.default.gray(o)}
|
|
1636
1641
|
${b2(this.state)} ${t.message}
|
|
@@ -1746,9 +1751,9 @@ var J = `${import_picocolors2.default.gray(o)} `;
|
|
|
1746
1751
|
|
|
1747
1752
|
// src/interactive.ts
|
|
1748
1753
|
function formatDetectedCount(count) {
|
|
1749
|
-
if (
|
|
1754
|
+
if (count === undefined)
|
|
1750
1755
|
return "available";
|
|
1751
|
-
return `${count.toLocaleString()}
|
|
1756
|
+
return `${count.toLocaleString()} chats`;
|
|
1752
1757
|
}
|
|
1753
1758
|
function ensureValue(value) {
|
|
1754
1759
|
if (pD(value)) {
|
|
@@ -1757,74 +1762,63 @@ function ensureValue(value) {
|
|
|
1757
1762
|
}
|
|
1758
1763
|
return value;
|
|
1759
1764
|
}
|
|
1760
|
-
|
|
1765
|
+
function startSetup() {
|
|
1761
1766
|
Ie("Conare setup");
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
const resolved = value.trim() || options.savedApiKey || "";
|
|
1769
|
-
if (!resolved)
|
|
1770
|
-
return "Enter an API key from https://mcp.conare.ai";
|
|
1771
|
-
if (!resolved.startsWith("cmem_"))
|
|
1772
|
-
return "API keys start with cmem_";
|
|
1773
|
-
return;
|
|
1774
|
-
}
|
|
1775
|
-
});
|
|
1776
|
-
apiKey = ensureValue(keyPrompt).trim() || options.savedApiKey;
|
|
1777
|
-
}
|
|
1778
|
-
Me(options.detectedTargets.map((target) => `• ${target.label}: ${target.available === false ? "not detected" : formatDetectedCount(target.detectedCount)}`).join(`
|
|
1767
|
+
}
|
|
1768
|
+
function finishSetup() {
|
|
1769
|
+
Se("Starting setup...");
|
|
1770
|
+
}
|
|
1771
|
+
function showDetectedApps(targets) {
|
|
1772
|
+
Me(targets.map((target) => `• ${target.label}: ${target.available === false ? "not detected" : formatDetectedCount(target.detectedCount)}`).join(`
|
|
1779
1773
|
`), "Detected apps");
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
}
|
|
1796
|
-
}
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1774
|
+
}
|
|
1775
|
+
async function promptApiKey(options) {
|
|
1776
|
+
if (options.providedApiKey) {
|
|
1777
|
+
return options.providedApiKey;
|
|
1778
|
+
}
|
|
1779
|
+
const keyPrompt = await ge({
|
|
1780
|
+
message: options.savedApiKey ? `API key (press Enter to use saved key ending in ${options.savedApiKey.slice(-6)})` : "API key",
|
|
1781
|
+
mask: "*",
|
|
1782
|
+
validate(value) {
|
|
1783
|
+
const resolved = value.trim() || options.savedApiKey || "";
|
|
1784
|
+
if (!resolved)
|
|
1785
|
+
return "Enter an API key from https://mcp.conare.ai";
|
|
1786
|
+
if (!resolved.startsWith("cmem_"))
|
|
1787
|
+
return "API keys start with cmem_";
|
|
1788
|
+
return;
|
|
1789
|
+
}
|
|
1790
|
+
});
|
|
1791
|
+
return ensureValue(keyPrompt).trim() || options.savedApiKey;
|
|
1792
|
+
}
|
|
1793
|
+
async function selectChatSources(targets) {
|
|
1794
|
+
return ensureValue(await fe({
|
|
1795
|
+
message: "Select chat sources",
|
|
1796
|
+
required: false,
|
|
1797
|
+
initialValues: targets.filter((target) => target.recommended).map((target) => target.id),
|
|
1798
|
+
options: targets.map((target) => ({
|
|
1799
|
+
value: target.id,
|
|
1800
|
+
label: target.label,
|
|
1801
|
+
hint: target.available === false ? "not detected" : formatDetectedCount(target.detectedCount)
|
|
1802
|
+
}))
|
|
1800
1803
|
}));
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
message: "Project path",
|
|
1805
|
-
placeholder: "."
|
|
1806
|
-
});
|
|
1807
|
-
indexPath = ensureValue(pathPrompt).trim() || ".";
|
|
1808
|
-
}
|
|
1809
|
-
const configureTargets = ensureValue(await fe({
|
|
1804
|
+
}
|
|
1805
|
+
async function selectMcpTargets(targets) {
|
|
1806
|
+
return ensureValue(await fe({
|
|
1810
1807
|
message: "Select where to install the MCP",
|
|
1811
1808
|
required: false,
|
|
1812
|
-
initialValues:
|
|
1813
|
-
options:
|
|
1809
|
+
initialValues: targets.filter((target) => target.recommended).map((target) => target.id),
|
|
1810
|
+
options: targets.map((target) => ({
|
|
1814
1811
|
value: target.id,
|
|
1815
1812
|
label: target.label,
|
|
1816
1813
|
hint: target.available === false ? "not detected" : "recommended"
|
|
1817
1814
|
}))
|
|
1818
1815
|
}));
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
indexCodebase: indexCodebase2,
|
|
1826
|
-
indexPath
|
|
1827
|
-
};
|
|
1816
|
+
}
|
|
1817
|
+
async function confirmIndexCodebase() {
|
|
1818
|
+
return ensureValue(await ye({
|
|
1819
|
+
message: "Index this codebase too?",
|
|
1820
|
+
initialValue: false
|
|
1821
|
+
}));
|
|
1828
1822
|
}
|
|
1829
1823
|
|
|
1830
1824
|
// src/index.ts
|
|
@@ -1936,29 +1930,34 @@ async function main() {
|
|
|
1936
1930
|
let postIngestIndexPath;
|
|
1937
1931
|
let selectedSources = opts.source ? [opts.source] : ["claude", "cursor", "codex"];
|
|
1938
1932
|
let apiKey = opts.key || process.env.CONARE_API_KEY || savedApiKey;
|
|
1933
|
+
let interactiveTargets = MCP_TARGETS.map((target) => ({
|
|
1934
|
+
id: target.id,
|
|
1935
|
+
label: target.label,
|
|
1936
|
+
available: true,
|
|
1937
|
+
recommended: true,
|
|
1938
|
+
detectedCount: undefined
|
|
1939
|
+
}));
|
|
1940
|
+
let interactiveMode = false;
|
|
1939
1941
|
if (shouldRunInteractive) {
|
|
1940
1942
|
const detectedTools = detect();
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
recommended: detected?.available !== false,
|
|
1951
|
-
detectedCount: detected?.sessionCount
|
|
1952
|
-
};
|
|
1953
|
-
})
|
|
1943
|
+
interactiveTargets = MCP_TARGETS.map((target) => {
|
|
1944
|
+
const detected = detectedTools.find((tool) => target.id === "claude" && tool.name === "Claude Code" || target.id === "cursor" && tool.name === "Cursor" || target.id === "codex" && tool.name === "Codex");
|
|
1945
|
+
return {
|
|
1946
|
+
id: target.id,
|
|
1947
|
+
label: target.label,
|
|
1948
|
+
available: detected?.available,
|
|
1949
|
+
recommended: detected?.available !== false,
|
|
1950
|
+
detectedCount: detected?.sessionCount
|
|
1951
|
+
};
|
|
1954
1952
|
});
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1953
|
+
startSetup();
|
|
1954
|
+
apiKey = await promptApiKey({
|
|
1955
|
+
savedApiKey,
|
|
1956
|
+
providedApiKey: opts.key
|
|
1957
|
+
}) || apiKey;
|
|
1958
|
+
showDetectedApps(interactiveTargets);
|
|
1959
|
+
selectedSources = await selectChatSources(interactiveTargets);
|
|
1960
|
+
interactiveMode = true;
|
|
1962
1961
|
}
|
|
1963
1962
|
if (!apiKey) {
|
|
1964
1963
|
printMissingKeyError();
|
|
@@ -2065,15 +2064,17 @@ Nothing new to index.`);
|
|
|
2065
2064
|
console.log();
|
|
2066
2065
|
}
|
|
2067
2066
|
const tools = detect();
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2067
|
+
if (!interactiveMode) {
|
|
2068
|
+
console.log("Detected AI tools:");
|
|
2069
|
+
for (const t of tools) {
|
|
2070
|
+
if (t.available) {
|
|
2071
|
+
console.log(` + ${t.name}${t.sessionCount || t.sessionCount === 0 ? ` — ${t.sessionCount} sessions` : ""}`);
|
|
2072
|
+
} else {
|
|
2073
|
+
console.log(` - ${t.name} (not found)`);
|
|
2074
|
+
}
|
|
2074
2075
|
}
|
|
2076
|
+
console.log();
|
|
2075
2077
|
}
|
|
2076
|
-
console.log();
|
|
2077
2078
|
const allMemories = [];
|
|
2078
2079
|
const shouldIngest = (name) => selectedSources.includes(name);
|
|
2079
2080
|
if (shouldIngest("claude") && tools.find((t) => t.name === "Claude Code")?.available) {
|
|
@@ -2149,6 +2150,20 @@ Nothing new to index.`);
|
|
|
2149
2150
|
}
|
|
2150
2151
|
}
|
|
2151
2152
|
console.log();
|
|
2153
|
+
if (interactiveMode) {
|
|
2154
|
+
selectedTargets = await selectMcpTargets(interactiveTargets);
|
|
2155
|
+
const shouldIndexCurrentCodebase = await confirmIndexCodebase();
|
|
2156
|
+
if (selectedTargets.length === 0 && selectedSources.length === 0 && !shouldIndexCurrentCodebase) {
|
|
2157
|
+
effectiveConfigOnly = false;
|
|
2158
|
+
effectiveIngestOnly = false;
|
|
2159
|
+
} else {
|
|
2160
|
+
effectiveIngestOnly = selectedTargets.length === 0;
|
|
2161
|
+
}
|
|
2162
|
+
if (shouldIndexCurrentCodebase) {
|
|
2163
|
+
postIngestIndexPath = ".";
|
|
2164
|
+
}
|
|
2165
|
+
finishSetup();
|
|
2166
|
+
}
|
|
2152
2167
|
if (!opts.dryRun && !effectiveIngestOnly) {
|
|
2153
2168
|
console.log("─── Configuring MCP ───");
|
|
2154
2169
|
console.log("");
|