conare 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +235 -193
- package/package.json +11 -2
package/dist/index.js
CHANGED
|
@@ -871,14 +871,14 @@ var init_interactive = __esm(() => {
|
|
|
871
871
|
});
|
|
872
872
|
|
|
873
873
|
// src/index.ts
|
|
874
|
-
import { existsSync as
|
|
874
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
875
875
|
import { join as join10 } from "node:path";
|
|
876
876
|
|
|
877
877
|
// src/detect.ts
|
|
878
|
-
import { existsSync, readdirSync } from "node:fs";
|
|
879
|
-
import { spawnSync } from "node:child_process";
|
|
878
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
880
879
|
import { join } from "node:path";
|
|
881
880
|
import { homedir, platform } from "node:os";
|
|
881
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
882
882
|
function countJsonlFiles(dir) {
|
|
883
883
|
let count = 0;
|
|
884
884
|
try {
|
|
@@ -892,50 +892,41 @@ function countJsonlFiles(dir) {
|
|
|
892
892
|
} catch {}
|
|
893
893
|
return count;
|
|
894
894
|
}
|
|
895
|
-
function countCursorSessions(dbPath) {
|
|
895
|
+
async function countCursorSessions(dbPath) {
|
|
896
896
|
try {
|
|
897
|
-
const
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
)
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
)
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
HAVING SUM(CASE WHEN type = 1 THEN 1 ELSE 0 END) > 0
|
|
926
|
-
AND SUM(CASE WHEN type = 2 THEN 1 ELSE 0 END) > 0
|
|
927
|
-
);
|
|
928
|
-
`.trim()
|
|
929
|
-
], { encoding: "utf-8" });
|
|
930
|
-
if (result.status !== 0)
|
|
931
|
-
return 0;
|
|
932
|
-
const count = Number.parseInt(result.stdout.trim(), 10);
|
|
933
|
-
return Number.isFinite(count) ? count : 0;
|
|
897
|
+
const require2 = createRequire2(import.meta.url);
|
|
898
|
+
const initSqlJs = require2("sql.js");
|
|
899
|
+
const SQL = await initSqlJs();
|
|
900
|
+
const buffer = readFileSync(dbPath);
|
|
901
|
+
const db = new SQL.Database(buffer);
|
|
902
|
+
try {
|
|
903
|
+
const results = db.exec("SELECT key, value FROM cursorDiskKV WHERE key LIKE 'composerData:%'");
|
|
904
|
+
if (results.length === 0)
|
|
905
|
+
return 0;
|
|
906
|
+
let count = 0;
|
|
907
|
+
for (const [, value] of results[0].values) {
|
|
908
|
+
try {
|
|
909
|
+
const parsed = JSON.parse(value);
|
|
910
|
+
const headers = parsed.fullConversationHeadersOnly;
|
|
911
|
+
if (!Array.isArray(headers) || headers.length < 2)
|
|
912
|
+
continue;
|
|
913
|
+
const hasUser = headers.some((h) => h.type === 1);
|
|
914
|
+
const hasAssistant = headers.some((h) => h.type === 2);
|
|
915
|
+
if (hasUser && hasAssistant)
|
|
916
|
+
count++;
|
|
917
|
+
} catch {
|
|
918
|
+
continue;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
return count;
|
|
922
|
+
} finally {
|
|
923
|
+
db.close();
|
|
924
|
+
}
|
|
934
925
|
} catch {
|
|
935
926
|
return 0;
|
|
936
927
|
}
|
|
937
928
|
}
|
|
938
|
-
function detect() {
|
|
929
|
+
async function detect() {
|
|
939
930
|
const home = homedir();
|
|
940
931
|
const tools = [];
|
|
941
932
|
const claudeDir = join(home, ".claude", "projects");
|
|
@@ -956,8 +947,8 @@ function detect() {
|
|
|
956
947
|
let sessionCount = 0;
|
|
957
948
|
if (existsSync(codexHistory)) {
|
|
958
949
|
try {
|
|
959
|
-
const { readFileSync } = __require("node:fs");
|
|
960
|
-
const lines =
|
|
950
|
+
const { readFileSync: readFileSync2 } = __require("node:fs");
|
|
951
|
+
const lines = readFileSync2(codexHistory, "utf-8").split(`
|
|
961
952
|
`).filter(Boolean);
|
|
962
953
|
const sessions = new Set(lines.map((l) => {
|
|
963
954
|
try {
|
|
@@ -992,7 +983,7 @@ function detect() {
|
|
|
992
983
|
name: "Cursor",
|
|
993
984
|
available: existsSync(cursorDbPath),
|
|
994
985
|
path: cursorDbPath,
|
|
995
|
-
sessionCount: existsSync(cursorDbPath) ? countCursorSessions(cursorDbPath) : 0
|
|
986
|
+
sessionCount: existsSync(cursorDbPath) ? await countCursorSessions(cursorDbPath) : 0
|
|
996
987
|
});
|
|
997
988
|
const openclawDir = join(home, ".openclaw");
|
|
998
989
|
tools.push({
|
|
@@ -1005,12 +996,12 @@ function detect() {
|
|
|
1005
996
|
}
|
|
1006
997
|
|
|
1007
998
|
// src/ingest/claude.ts
|
|
1008
|
-
import { readdirSync as readdirSync2, readFileSync as
|
|
999
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync3, existsSync as existsSync3 } from "node:fs";
|
|
1009
1000
|
import { join as join3, basename } from "node:path";
|
|
1010
|
-
import { homedir as homedir3 } from "node:os";
|
|
1001
|
+
import { homedir as homedir3, platform as platform2 } from "node:os";
|
|
1011
1002
|
|
|
1012
1003
|
// src/ingest/shared.ts
|
|
1013
|
-
import { existsSync as existsSync2, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
1004
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "node:fs";
|
|
1014
1005
|
import { createHash } from "node:crypto";
|
|
1015
1006
|
import { join as join2 } from "node:path";
|
|
1016
1007
|
import { homedir as homedir2 } from "node:os";
|
|
@@ -1030,6 +1021,15 @@ function cleanText(raw) {
|
|
|
1030
1021
|
text = text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "");
|
|
1031
1022
|
text = text.replace(/<attached-context[\s\S]*?<\/attached-context>/g, "");
|
|
1032
1023
|
text = text.replace(/<environment_context>[\s\S]*?<\/environment_context>/g, "");
|
|
1024
|
+
text = text.replace(/^\s*Base directory for this skill:[\s\S]*/g, "");
|
|
1025
|
+
text = text.replace(/\nBase directory for this skill:[\s\S]*/g, "");
|
|
1026
|
+
text = text.replace(/<!-- vibe-rules Integration -->[\s\S]*?<!-- \/vibe-rules Integration -->/g, "");
|
|
1027
|
+
text = text.replace(/<good-behaviour>[\s\S]*?<\/good-behaviour>/g, "");
|
|
1028
|
+
text = text.replace(/<frontend-design>[\s\S]*?<\/frontend-design>/g, "");
|
|
1029
|
+
text = text.replace(/<architecture>[\s\S]*?<\/architecture>/g, "");
|
|
1030
|
+
text = text.replace(/<task-notification>[\s\S]*?<\/task-notification>/g, "");
|
|
1031
|
+
text = text.replace(/<local-command-stdout>[\s\S]*?<\/local-command-stdout>/g, "");
|
|
1032
|
+
text = text.replace(/<system_instruction>[\s\S]*?<\/system_instruction>/g, "");
|
|
1033
1033
|
return text.trim();
|
|
1034
1034
|
}
|
|
1035
1035
|
function createContentHash(content) {
|
|
@@ -1038,7 +1038,7 @@ function createContentHash(content) {
|
|
|
1038
1038
|
function getIngested() {
|
|
1039
1039
|
try {
|
|
1040
1040
|
if (existsSync2(MANIFEST_PATH)) {
|
|
1041
|
-
return JSON.parse(
|
|
1041
|
+
return JSON.parse(readFileSync2(MANIFEST_PATH, "utf-8"));
|
|
1042
1042
|
}
|
|
1043
1043
|
} catch {}
|
|
1044
1044
|
return {};
|
|
@@ -1075,6 +1075,43 @@ function clearIngested(source) {
|
|
|
1075
1075
|
// src/ingest/claude.ts
|
|
1076
1076
|
var MAX_CONTENT = 48000;
|
|
1077
1077
|
var MIN_TURN_LEN = 50;
|
|
1078
|
+
function resolveProjectName(dirName) {
|
|
1079
|
+
const segments = dirName.replace(/^-/, "").split("-");
|
|
1080
|
+
const isWindows = platform2() === "win32";
|
|
1081
|
+
let resolved;
|
|
1082
|
+
let startIdx;
|
|
1083
|
+
if (isWindows && segments.length > 0 && /^[A-Za-z]$/.test(segments[0])) {
|
|
1084
|
+
resolved = segments[0].toUpperCase() + ":\\";
|
|
1085
|
+
startIdx = 1;
|
|
1086
|
+
} else {
|
|
1087
|
+
resolved = "/";
|
|
1088
|
+
startIdx = 0;
|
|
1089
|
+
}
|
|
1090
|
+
let i = startIdx;
|
|
1091
|
+
while (i < segments.length) {
|
|
1092
|
+
let found = false;
|
|
1093
|
+
for (let end = segments.length;end > i; end--) {
|
|
1094
|
+
const candidate = segments.slice(i, end).join("-");
|
|
1095
|
+
const candidatePath = join3(resolved, candidate);
|
|
1096
|
+
if (existsSync3(candidatePath)) {
|
|
1097
|
+
resolved = candidatePath;
|
|
1098
|
+
i = end;
|
|
1099
|
+
found = true;
|
|
1100
|
+
break;
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
if (!found) {
|
|
1104
|
+
resolved = join3(resolved, segments[i]);
|
|
1105
|
+
i++;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
const home = homedir3();
|
|
1109
|
+
const sep = isWindows ? "\\" : "/";
|
|
1110
|
+
if (resolved.startsWith(home + sep)) {
|
|
1111
|
+
return resolved.slice(home.length + 1).replace(/\\/g, "/");
|
|
1112
|
+
}
|
|
1113
|
+
return resolved.replace(/\\/g, "/");
|
|
1114
|
+
}
|
|
1078
1115
|
function extractText(content) {
|
|
1079
1116
|
if (typeof content === "string")
|
|
1080
1117
|
return content;
|
|
@@ -1140,7 +1177,7 @@ function ingestClaude() {
|
|
|
1140
1177
|
}
|
|
1141
1178
|
for (const projDir of projectDirs) {
|
|
1142
1179
|
const projPath = join3(projectsDir, projDir);
|
|
1143
|
-
const project = projDir
|
|
1180
|
+
const project = resolveProjectName(projDir);
|
|
1144
1181
|
let files;
|
|
1145
1182
|
try {
|
|
1146
1183
|
files = readdirSync2(projPath).filter((f) => f.endsWith(".jsonl"));
|
|
@@ -1149,7 +1186,7 @@ function ingestClaude() {
|
|
|
1149
1186
|
}
|
|
1150
1187
|
for (const file of files) {
|
|
1151
1188
|
const sessionId = basename(file, ".jsonl");
|
|
1152
|
-
const raw =
|
|
1189
|
+
const raw = readFileSync3(join3(projPath, file), "utf-8");
|
|
1153
1190
|
const { turns, date } = parseSession(raw.split(`
|
|
1154
1191
|
`));
|
|
1155
1192
|
if (turns.length === 0) {
|
|
@@ -1158,8 +1195,7 @@ function ingestClaude() {
|
|
|
1158
1195
|
}
|
|
1159
1196
|
const header = `# Chat: ${project}${date ? ` | ${date}` : ""}`;
|
|
1160
1197
|
const body = turns.map((t) => {
|
|
1161
|
-
|
|
1162
|
-
return `## Q: ${q}
|
|
1198
|
+
return `## Q: ${t.user}
|
|
1163
1199
|
|
|
1164
1200
|
${t.assistant}`;
|
|
1165
1201
|
}).join(`
|
|
@@ -1200,105 +1236,33 @@ ${body}`;
|
|
|
1200
1236
|
}
|
|
1201
1237
|
|
|
1202
1238
|
// src/ingest/codex.ts
|
|
1203
|
-
import { existsSync as
|
|
1239
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, readdirSync as readdirSync3 } from "node:fs";
|
|
1204
1240
|
import { join as join4, basename as basename2 } from "node:path";
|
|
1205
1241
|
import { homedir as homedir4 } from "node:os";
|
|
1206
1242
|
var MAX_CONTENT2 = 48000;
|
|
1207
1243
|
function isCodexBoilerplate(text) {
|
|
1208
1244
|
return text.startsWith("# AGENTS.md instructions for") || text.startsWith("<INSTRUCTIONS>") || text.startsWith("<user_instructions>") || text.startsWith("<user_action>");
|
|
1209
1245
|
}
|
|
1210
|
-
function
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
if (cwdMatch)
|
|
1214
|
-
cwd = cwdMatch[1];
|
|
1215
|
-
const cleaned = text.replace(/<environment_context>[\s\S]*?<\/environment_context>/g, "").trim();
|
|
1216
|
-
return { text: cleaned, cwd };
|
|
1246
|
+
function extractCwd(text) {
|
|
1247
|
+
const match = text.match(/<cwd>([^<]+)<\/cwd>/);
|
|
1248
|
+
return match ? match[1] : null;
|
|
1217
1249
|
}
|
|
1218
1250
|
function projectFromCwd(cwd) {
|
|
1219
|
-
|
|
1251
|
+
const home = homedir4();
|
|
1252
|
+
const normalized = cwd.replace(/\\/g, "/");
|
|
1253
|
+
const normalizedHome = home.replace(/\\/g, "/");
|
|
1254
|
+
if (normalized.startsWith(normalizedHome + "/")) {
|
|
1255
|
+
return normalized.slice(normalizedHome.length + 1);
|
|
1256
|
+
}
|
|
1257
|
+
return normalized.replace(/^\/Users\/[^/]+\//, "").replace(/^\/home\/[^/]+\//, "").replace(/^[A-Za-z]:\/Users\/[^/]+\//, "");
|
|
1220
1258
|
}
|
|
1221
1259
|
function ingestCodex() {
|
|
1222
1260
|
const memories = [];
|
|
1223
1261
|
const sessionIds = [];
|
|
1224
1262
|
let filtered = 0;
|
|
1225
1263
|
let deduped = 0;
|
|
1226
|
-
const historyPath = join4(homedir4(), ".codex", "history.jsonl");
|
|
1227
|
-
if (existsSync3(historyPath)) {
|
|
1228
|
-
try {
|
|
1229
|
-
const lines = readFileSync3(historyPath, "utf-8").split(`
|
|
1230
|
-
`).filter(Boolean);
|
|
1231
|
-
const sessions = new Map;
|
|
1232
|
-
for (const line of lines) {
|
|
1233
|
-
try {
|
|
1234
|
-
const obj = JSON.parse(line);
|
|
1235
|
-
if (!obj.session_id || !obj.text)
|
|
1236
|
-
continue;
|
|
1237
|
-
if (!sessions.has(obj.session_id))
|
|
1238
|
-
sessions.set(obj.session_id, []);
|
|
1239
|
-
sessions.get(obj.session_id).push({ ts: obj.ts, text: obj.text });
|
|
1240
|
-
} catch {
|
|
1241
|
-
continue;
|
|
1242
|
-
}
|
|
1243
|
-
}
|
|
1244
|
-
for (const [sessionId, entries] of sessions) {
|
|
1245
|
-
entries.sort((a, b) => a.ts - b.ts);
|
|
1246
|
-
const date = new Date(entries[0].ts * 1000).toISOString().slice(0, 10);
|
|
1247
|
-
let project = null;
|
|
1248
|
-
const cleanEntries = [];
|
|
1249
|
-
for (const e of entries) {
|
|
1250
|
-
let text = cleanText(e.text);
|
|
1251
|
-
if (isCodexBoilerplate(text))
|
|
1252
|
-
continue;
|
|
1253
|
-
const env = stripEnvironmentContext(text);
|
|
1254
|
-
text = env.text;
|
|
1255
|
-
if (!project && env.cwd)
|
|
1256
|
-
project = projectFromCwd(env.cwd);
|
|
1257
|
-
if (text.length === 0)
|
|
1258
|
-
continue;
|
|
1259
|
-
cleanEntries.push(text.length > 300 ? text.slice(0, 300) + "..." : text);
|
|
1260
|
-
}
|
|
1261
|
-
const body = cleanEntries.filter(Boolean).join(`
|
|
1262
|
-
|
|
1263
|
-
---
|
|
1264
|
-
|
|
1265
|
-
`);
|
|
1266
|
-
let content = `# Codex Chat | ${date}
|
|
1267
|
-
|
|
1268
|
-
${body}`;
|
|
1269
|
-
if (content.length > MAX_CONTENT2)
|
|
1270
|
-
content = content.slice(0, MAX_CONTENT2) + `
|
|
1271
|
-
|
|
1272
|
-
[truncated]`;
|
|
1273
|
-
if (content.length < 100) {
|
|
1274
|
-
filtered++;
|
|
1275
|
-
continue;
|
|
1276
|
-
}
|
|
1277
|
-
const contentHash = createContentHash(content);
|
|
1278
|
-
const dedupKey = `codex:${sessionId}`;
|
|
1279
|
-
const fingerprint = `${dedupKey}:${contentHash}`;
|
|
1280
|
-
if (isIngested("codex", fingerprint)) {
|
|
1281
|
-
deduped++;
|
|
1282
|
-
continue;
|
|
1283
|
-
}
|
|
1284
|
-
memories.push({
|
|
1285
|
-
content,
|
|
1286
|
-
containerTag: "codex-chats",
|
|
1287
|
-
metadata: {
|
|
1288
|
-
dedupKey,
|
|
1289
|
-
contentHash,
|
|
1290
|
-
source: "codex",
|
|
1291
|
-
sessionId,
|
|
1292
|
-
date,
|
|
1293
|
-
...project ? { project } : {}
|
|
1294
|
-
}
|
|
1295
|
-
});
|
|
1296
|
-
sessionIds.push(sessionId);
|
|
1297
|
-
}
|
|
1298
|
-
} catch {}
|
|
1299
|
-
}
|
|
1300
1264
|
const sessionsDir = join4(homedir4(), ".codex", "sessions");
|
|
1301
|
-
if (
|
|
1265
|
+
if (existsSync4(sessionsDir)) {
|
|
1302
1266
|
try {
|
|
1303
1267
|
const stats = { filtered: 0, deduped: 0 };
|
|
1304
1268
|
walkCodexSessions(sessionsDir, memories, sessionIds, stats);
|
|
@@ -1315,10 +1279,8 @@ function walkCodexSessions(dir, memories, sessionIds, stats) {
|
|
|
1315
1279
|
walkCodexSessions(join4(dir, entry.name), memories, sessionIds, stats);
|
|
1316
1280
|
} else if (entry.name.endsWith(".jsonl")) {
|
|
1317
1281
|
const sessionId = basename2(entry.name, ".jsonl");
|
|
1318
|
-
if (sessionIds.includes(sessionId))
|
|
1319
|
-
continue;
|
|
1320
1282
|
try {
|
|
1321
|
-
const lines =
|
|
1283
|
+
const lines = readFileSync4(join4(dir, entry.name), "utf-8").split(`
|
|
1322
1284
|
`).filter(Boolean);
|
|
1323
1285
|
let date = null;
|
|
1324
1286
|
let project = null;
|
|
@@ -1329,19 +1291,29 @@ function walkCodexSessions(dir, memories, sessionIds, stats) {
|
|
|
1329
1291
|
try {
|
|
1330
1292
|
const obj = JSON.parse(line);
|
|
1331
1293
|
if (!date && obj.timestamp)
|
|
1332
|
-
date = obj.timestamp.slice(0, 10);
|
|
1294
|
+
date = typeof obj.timestamp === "string" ? obj.timestamp.slice(0, 10) : null;
|
|
1333
1295
|
if (obj.type === "session_meta" && obj.payload?.cwd) {
|
|
1334
1296
|
project = projectFromCwd(obj.payload.cwd);
|
|
1335
1297
|
}
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1298
|
+
let role;
|
|
1299
|
+
let msgContent;
|
|
1300
|
+
if (obj.type === "response_item" && obj.payload?.type === "message") {
|
|
1301
|
+
role = obj.payload.role;
|
|
1302
|
+
msgContent = Array.isArray(obj.payload.content) ? obj.payload.content : undefined;
|
|
1303
|
+
} else if (obj.type === "message" && obj.role) {
|
|
1304
|
+
role = obj.role;
|
|
1305
|
+
msgContent = Array.isArray(obj.content) ? obj.content : undefined;
|
|
1306
|
+
}
|
|
1307
|
+
if (!role || !msgContent)
|
|
1341
1308
|
continue;
|
|
1342
1309
|
if (role === "user") {
|
|
1343
1310
|
for (const block of msgContent) {
|
|
1344
1311
|
if (block.type === "input_text" && block.text) {
|
|
1312
|
+
if (!project) {
|
|
1313
|
+
const cwd = extractCwd(block.text);
|
|
1314
|
+
if (cwd)
|
|
1315
|
+
project = projectFromCwd(cwd);
|
|
1316
|
+
}
|
|
1345
1317
|
const text = cleanText(block.text);
|
|
1346
1318
|
if (isCodexBoilerplate(text))
|
|
1347
1319
|
continue;
|
|
@@ -1376,11 +1348,10 @@ function walkCodexSessions(dir, memories, sessionIds, stats) {
|
|
|
1376
1348
|
continue;
|
|
1377
1349
|
}
|
|
1378
1350
|
const body = rounds.map((r) => {
|
|
1379
|
-
const q = r.user.length > 300 ? r.user.slice(0, 300) + "..." : r.user;
|
|
1380
1351
|
const assistant = r.assistantParts.join(`
|
|
1381
1352
|
|
|
1382
1353
|
`);
|
|
1383
|
-
return `## Q: ${
|
|
1354
|
+
return `## Q: ${r.user}
|
|
1384
1355
|
|
|
1385
1356
|
${assistant}`;
|
|
1386
1357
|
}).join(`
|
|
@@ -1422,9 +1393,9 @@ ${body}`;
|
|
|
1422
1393
|
}
|
|
1423
1394
|
|
|
1424
1395
|
// src/ingest/cursor.ts
|
|
1425
|
-
import { readFileSync as
|
|
1396
|
+
import { readFileSync as readFileSync5, statSync } from "node:fs";
|
|
1426
1397
|
import { join as join5 } from "node:path";
|
|
1427
|
-
import { createRequire as
|
|
1398
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
1428
1399
|
var MAX_CONTENT3 = 48000;
|
|
1429
1400
|
var MAX_DB_SIZE = 2 * 1024 * 1024 * 1024;
|
|
1430
1401
|
var WARN_DB_SIZE = 500 * 1024 * 1024;
|
|
@@ -1432,10 +1403,10 @@ var MIN_TURN_LEN2 = 50;
|
|
|
1432
1403
|
function loadSqlJs(wasmDir) {
|
|
1433
1404
|
try {
|
|
1434
1405
|
if (wasmDir) {
|
|
1435
|
-
const require2 =
|
|
1406
|
+
const require2 = createRequire3(join5(wasmDir, "sql.js", "package.json"));
|
|
1436
1407
|
return require2("sql.js");
|
|
1437
1408
|
} else {
|
|
1438
|
-
const require2 =
|
|
1409
|
+
const require2 = createRequire3(import.meta.url);
|
|
1439
1410
|
return require2("sql.js");
|
|
1440
1411
|
}
|
|
1441
1412
|
} catch {
|
|
@@ -1448,7 +1419,7 @@ function openDb(initSqlJs, dbPath, wasmDir) {
|
|
|
1448
1419
|
locateOpts.locateFile = (file) => join5(wasmDir, "sql.js", "dist", file);
|
|
1449
1420
|
}
|
|
1450
1421
|
return initSqlJs(locateOpts).then((SQL) => {
|
|
1451
|
-
const buffer =
|
|
1422
|
+
const buffer = readFileSync5(dbPath);
|
|
1452
1423
|
return new SQL.Database(buffer);
|
|
1453
1424
|
});
|
|
1454
1425
|
}
|
|
@@ -1542,8 +1513,7 @@ async function ingestCursor(dbPath, wasmDir) {
|
|
|
1542
1513
|
const date = parsed.createdAt ? new Date(parsed.createdAt).toISOString().slice(0, 10) : "unknown";
|
|
1543
1514
|
const header = `# ${sessionName} | ${date}`;
|
|
1544
1515
|
const body = turns.map((t) => {
|
|
1545
|
-
|
|
1546
|
-
return `## Q: ${q}
|
|
1516
|
+
return `## Q: ${t.user}
|
|
1547
1517
|
|
|
1548
1518
|
${t.assistant}`;
|
|
1549
1519
|
}).join(`
|
|
@@ -1589,7 +1559,7 @@ ${body}`;
|
|
|
1589
1559
|
|
|
1590
1560
|
// src/ingest/codebase.ts
|
|
1591
1561
|
import { createHash as createHash2 } from "node:crypto";
|
|
1592
|
-
import { readdirSync as readdirSync4, readFileSync as
|
|
1562
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync2, existsSync as existsSync5 } from "node:fs";
|
|
1593
1563
|
import { join as join6, relative, extname, resolve } from "node:path";
|
|
1594
1564
|
var DEFAULT_IGNORE = new Set([
|
|
1595
1565
|
"node_modules",
|
|
@@ -1676,10 +1646,10 @@ var MAX_FILE_SIZE = 1e5;
|
|
|
1676
1646
|
function parseGitignore(rootPath) {
|
|
1677
1647
|
const patterns = new Set;
|
|
1678
1648
|
const gitignorePath = join6(rootPath, ".gitignore");
|
|
1679
|
-
if (!
|
|
1649
|
+
if (!existsSync5(gitignorePath))
|
|
1680
1650
|
return patterns;
|
|
1681
1651
|
try {
|
|
1682
|
-
const content =
|
|
1652
|
+
const content = readFileSync6(gitignorePath, "utf-8");
|
|
1683
1653
|
for (const line of content.split(`
|
|
1684
1654
|
`)) {
|
|
1685
1655
|
const trimmed = line.trim();
|
|
@@ -1792,7 +1762,7 @@ function indexCodebase(rootPath) {
|
|
|
1792
1762
|
}
|
|
1793
1763
|
let raw;
|
|
1794
1764
|
try {
|
|
1795
|
-
raw =
|
|
1765
|
+
raw = readFileSync6(fullPath, "utf-8");
|
|
1796
1766
|
} catch {
|
|
1797
1767
|
skipped++;
|
|
1798
1768
|
continue;
|
|
@@ -1962,10 +1932,10 @@ async function uploadBulk(apiKey, memories, onProgress) {
|
|
|
1962
1932
|
}
|
|
1963
1933
|
|
|
1964
1934
|
// src/configure.ts
|
|
1965
|
-
import { existsSync as
|
|
1935
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync7, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1966
1936
|
import { dirname, join as join7 } from "node:path";
|
|
1967
|
-
import { homedir as homedir5 } from "node:os";
|
|
1968
|
-
import { spawnSync
|
|
1937
|
+
import { homedir as homedir5, platform as platform4 } from "node:os";
|
|
1938
|
+
import { spawnSync } from "node:child_process";
|
|
1969
1939
|
var CONARE_URL = "https://mcp.conare.ai";
|
|
1970
1940
|
var SERVER_NAME = "conare-memory";
|
|
1971
1941
|
var MCP_TARGETS = [
|
|
@@ -1976,7 +1946,7 @@ var MCP_TARGETS = [
|
|
|
1976
1946
|
];
|
|
1977
1947
|
function readJsonFile(path) {
|
|
1978
1948
|
try {
|
|
1979
|
-
return JSON.parse(
|
|
1949
|
+
return JSON.parse(readFileSync7(path, "utf-8"));
|
|
1980
1950
|
} catch {
|
|
1981
1951
|
return {};
|
|
1982
1952
|
}
|
|
@@ -2006,13 +1976,14 @@ function upsertMcpServer(path, apiKey) {
|
|
|
2006
1976
|
function configureClaude(apiKey) {
|
|
2007
1977
|
const claudeConfigPath = join7(homedir5(), ".claude.json");
|
|
2008
1978
|
const claudeMcpPath = join7(homedir5(), ".claude", "mcp.json");
|
|
2009
|
-
if (
|
|
2010
|
-
stdio: "ignore"
|
|
1979
|
+
if (spawnSync("claude", ["mcp", "add-json", SERVER_NAME, "--scope", "user", JSON.stringify(getServerConfig(apiKey))], {
|
|
1980
|
+
stdio: "ignore",
|
|
1981
|
+
shell: platform4() === "win32"
|
|
2011
1982
|
}).status === 0) {
|
|
2012
1983
|
return "Claude Code configured via `claude mcp add-json`";
|
|
2013
1984
|
}
|
|
2014
1985
|
upsertMcpServer(claudeConfigPath, apiKey);
|
|
2015
|
-
if (
|
|
1986
|
+
if (existsSync6(join7(homedir5(), ".claude"))) {
|
|
2016
1987
|
upsertMcpServer(claudeMcpPath, apiKey);
|
|
2017
1988
|
}
|
|
2018
1989
|
return `Claude Code configured at ${claudeConfigPath}`;
|
|
@@ -2039,16 +2010,16 @@ function configureMcp(apiKey, targets = ["claude", "cursor", "codex"]) {
|
|
|
2039
2010
|
}
|
|
2040
2011
|
|
|
2041
2012
|
// src/config.ts
|
|
2042
|
-
import { existsSync as
|
|
2013
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync3 } from "node:fs";
|
|
2043
2014
|
import { join as join8 } from "node:path";
|
|
2044
2015
|
import { homedir as homedir6 } from "node:os";
|
|
2045
2016
|
var CONFIG_DIR = join8(homedir6(), ".conare");
|
|
2046
2017
|
var CONFIG_PATH = join8(CONFIG_DIR, "config.json");
|
|
2047
2018
|
function readConfig() {
|
|
2048
2019
|
try {
|
|
2049
|
-
if (!
|
|
2020
|
+
if (!existsSync7(CONFIG_PATH))
|
|
2050
2021
|
return {};
|
|
2051
|
-
return JSON.parse(
|
|
2022
|
+
return JSON.parse(readFileSync8(CONFIG_PATH, "utf-8"));
|
|
2052
2023
|
} catch {
|
|
2053
2024
|
return {};
|
|
2054
2025
|
}
|
|
@@ -2063,9 +2034,9 @@ function getSavedApiKey() {
|
|
|
2063
2034
|
}
|
|
2064
2035
|
|
|
2065
2036
|
// src/sync.ts
|
|
2066
|
-
import { existsSync as
|
|
2037
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4, unlinkSync, readFileSync as readFileSync9, chmodSync, cpSync, rmSync, symlinkSync, readlinkSync, appendFileSync } from "node:fs";
|
|
2067
2038
|
import { join as join9, dirname as dirname2 } from "node:path";
|
|
2068
|
-
import { homedir as homedir7, platform as
|
|
2039
|
+
import { homedir as homedir7, platform as platform5 } from "node:os";
|
|
2069
2040
|
import { execSync } from "node:child_process";
|
|
2070
2041
|
var CONARE_DIR = join9(homedir7(), ".conare");
|
|
2071
2042
|
var BIN_DIR = join9(CONARE_DIR, "bin");
|
|
@@ -2075,6 +2046,40 @@ var PLIST_PATH = join9(homedir7(), "Library", "LaunchAgents", `${PLIST_LABEL}.pl
|
|
|
2075
2046
|
var SYSTEMD_DIR = join9(homedir7(), ".config", "systemd", "user");
|
|
2076
2047
|
var SYSTEMD_SERVICE = join9(SYSTEMD_DIR, "conare-sync.service");
|
|
2077
2048
|
var SYSTEMD_TIMER = join9(SYSTEMD_DIR, "conare-sync.timer");
|
|
2049
|
+
var TASK_NAME = "ConareMemorySync";
|
|
2050
|
+
var RUN_CMD = `@echo off
|
|
2051
|
+
REM Conare Memory — background sync wrapper (Windows)
|
|
2052
|
+
setlocal
|
|
2053
|
+
|
|
2054
|
+
set "CONARE_DIR=%USERPROFILE%\\.conare"
|
|
2055
|
+
set "LOG=%CONARE_DIR%\\ingest.log"
|
|
2056
|
+
set "LOCKFILE=%CONARE_DIR%\\sync.lock.d"
|
|
2057
|
+
|
|
2058
|
+
REM File lock: prevent concurrent runs
|
|
2059
|
+
if exist "%LOCKFILE%" (
|
|
2060
|
+
echo %DATE% %TIME% SKIP: another instance running >> "%LOG%"
|
|
2061
|
+
exit /b 0
|
|
2062
|
+
)
|
|
2063
|
+
mkdir "%LOCKFILE%" 2>nul
|
|
2064
|
+
if errorlevel 1 (
|
|
2065
|
+
echo %DATE% %TIME% SKIP: lock failed >> "%LOG%"
|
|
2066
|
+
exit /b 0
|
|
2067
|
+
)
|
|
2068
|
+
|
|
2069
|
+
REM Resolve node
|
|
2070
|
+
where node >nul 2>nul
|
|
2071
|
+
if errorlevel 1 (
|
|
2072
|
+
echo %DATE% %TIME% ERROR: node not found >> "%LOG%"
|
|
2073
|
+
rmdir "%LOCKFILE%" 2>nul
|
|
2074
|
+
exit /b 1
|
|
2075
|
+
)
|
|
2076
|
+
|
|
2077
|
+
echo %DATE% %TIME% START sync >> "%LOG%"
|
|
2078
|
+
node "%CONARE_DIR%\\bin\\conare-ingest.mjs" --config-file "%CONARE_DIR%\\config.json" --ingest-only --quiet 2>> "%LOG%"
|
|
2079
|
+
echo %DATE% %TIME% DONE sync (exit %ERRORLEVEL%) >> "%LOG%"
|
|
2080
|
+
|
|
2081
|
+
rmdir "%LOCKFILE%" 2>nul
|
|
2082
|
+
`;
|
|
2078
2083
|
var RUN_SH = `#!/bin/bash
|
|
2079
2084
|
# Conare Memory — background sync wrapper
|
|
2080
2085
|
# Resolves node at runtime to survive nvm/fnm upgrades
|
|
@@ -2205,7 +2210,7 @@ function persistBinary(apiKey) {
|
|
|
2205
2210
|
throw new Error("Could not locate CLI bundle. Run from an installed conare package.");
|
|
2206
2211
|
}
|
|
2207
2212
|
const dest = join9(BIN_DIR, "conare-ingest.mjs");
|
|
2208
|
-
const content =
|
|
2213
|
+
const content = readFileSync9(cliEntry, "utf-8");
|
|
2209
2214
|
writeFileSync4(dest, content);
|
|
2210
2215
|
const sqlJsDir = findSqlJs();
|
|
2211
2216
|
if (sqlJsDir) {
|
|
@@ -2217,20 +2222,24 @@ function persistBinary(apiKey) {
|
|
|
2217
2222
|
}
|
|
2218
2223
|
const runShPath = join9(BIN_DIR, "run.sh");
|
|
2219
2224
|
writeFileSync4(runShPath, RUN_SH);
|
|
2220
|
-
|
|
2225
|
+
try {
|
|
2226
|
+
chmodSync(runShPath, 493);
|
|
2227
|
+
} catch {}
|
|
2228
|
+
const runCmdPath = join9(BIN_DIR, "run.cmd");
|
|
2229
|
+
writeFileSync4(runCmdPath, RUN_CMD);
|
|
2221
2230
|
writeFileSync4(CONFIG_PATH2, JSON.stringify({ apiKey }, null, 2) + `
|
|
2222
2231
|
`);
|
|
2223
2232
|
}
|
|
2224
2233
|
function findCliBundle() {
|
|
2225
2234
|
const entry = process.argv[1];
|
|
2226
|
-
if (entry &&
|
|
2235
|
+
if (entry && existsSync8(entry))
|
|
2227
2236
|
return entry;
|
|
2228
2237
|
const candidates = [
|
|
2229
2238
|
join9(dirname2(new URL(import.meta.url).pathname), "index.js"),
|
|
2230
2239
|
join9(dirname2(new URL(import.meta.url).pathname), "..", "dist", "index.js")
|
|
2231
2240
|
];
|
|
2232
2241
|
for (const c of candidates) {
|
|
2233
|
-
if (
|
|
2242
|
+
if (existsSync8(c))
|
|
2234
2243
|
return c;
|
|
2235
2244
|
}
|
|
2236
2245
|
return null;
|
|
@@ -2242,7 +2251,7 @@ function findSqlJs() {
|
|
|
2242
2251
|
join9(dirname2(new URL(import.meta.url).pathname), "..", "..", "node_modules", "sql.js")
|
|
2243
2252
|
];
|
|
2244
2253
|
for (const c of candidates) {
|
|
2245
|
-
if (
|
|
2254
|
+
if (existsSync8(c))
|
|
2246
2255
|
return c;
|
|
2247
2256
|
}
|
|
2248
2257
|
return null;
|
|
@@ -2290,6 +2299,24 @@ function setupLinuxCron(intervalMinutes) {
|
|
|
2290
2299
|
}
|
|
2291
2300
|
}
|
|
2292
2301
|
function installGlobalCommand() {
|
|
2302
|
+
const isWindows = platform5() === "win32";
|
|
2303
|
+
if (isWindows) {
|
|
2304
|
+
const wrapper2 = join9(BIN_DIR, "conare.cmd");
|
|
2305
|
+
const content2 = `@echo off\r
|
|
2306
|
+
node "%USERPROFILE%\\.conare\\bin\\conare-ingest.mjs" %*\r
|
|
2307
|
+
`;
|
|
2308
|
+
writeFileSync4(wrapper2, content2);
|
|
2309
|
+
const pathDirs = (process.env.PATH || "").split(";");
|
|
2310
|
+
if (pathDirs.some((d) => d.toLowerCase() === BIN_DIR.toLowerCase())) {
|
|
2311
|
+
return "Global command: conare (via .conare\\bin in PATH)";
|
|
2312
|
+
}
|
|
2313
|
+
try {
|
|
2314
|
+
execSync(`powershell -NoProfile -Command "[Environment]::SetEnvironmentVariable('PATH', [Environment]::GetEnvironmentVariable('PATH','User') + ';${BIN_DIR}', 'User')"`, { stdio: "ignore" });
|
|
2315
|
+
return `Global command: conare (added .conare\\bin to user PATH — restart terminal)`;
|
|
2316
|
+
} catch {
|
|
2317
|
+
return `Global command: add ${BIN_DIR} to your PATH manually`;
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2293
2320
|
const wrapper = join9(BIN_DIR, "conare");
|
|
2294
2321
|
const content = `#!/bin/bash
|
|
2295
2322
|
# Conare global command — runs the persisted CLI bundle
|
|
@@ -2311,7 +2338,7 @@ exec "$NODE" "$CONARE_DIR/bin/conare-ingest.mjs" "$@"
|
|
|
2311
2338
|
chmodSync(wrapper, 493);
|
|
2312
2339
|
const symlinkTarget = "/usr/local/bin/conare";
|
|
2313
2340
|
try {
|
|
2314
|
-
if (
|
|
2341
|
+
if (existsSync8(symlinkTarget)) {
|
|
2315
2342
|
try {
|
|
2316
2343
|
const existing = readlinkSync(symlinkTarget);
|
|
2317
2344
|
if (existing === wrapper)
|
|
@@ -2329,7 +2356,7 @@ exec "$NODE" "$CONARE_DIR/bin/conare-ingest.mjs" "$@"
|
|
|
2329
2356
|
const shellProfile = getShellProfile();
|
|
2330
2357
|
if (shellProfile) {
|
|
2331
2358
|
try {
|
|
2332
|
-
const profileContent =
|
|
2359
|
+
const profileContent = existsSync8(shellProfile) ? readFileSync9(shellProfile, "utf-8") : "";
|
|
2333
2360
|
const exportLine = `export PATH="$HOME/.conare/bin:$PATH"`;
|
|
2334
2361
|
if (!profileContent.includes(".conare/bin")) {
|
|
2335
2362
|
appendFileSync(shellProfile, `
|
|
@@ -2353,19 +2380,26 @@ function getShellProfile() {
|
|
|
2353
2380
|
return join9(home, ".zshrc");
|
|
2354
2381
|
if (shell.includes("bash")) {
|
|
2355
2382
|
const profile = join9(home, ".bash_profile");
|
|
2356
|
-
if (
|
|
2383
|
+
if (platform5() === "darwin" && existsSync8(profile))
|
|
2357
2384
|
return profile;
|
|
2358
2385
|
return join9(home, ".bashrc");
|
|
2359
2386
|
}
|
|
2360
|
-
if (
|
|
2387
|
+
if (existsSync8(join9(home, ".zshrc")))
|
|
2361
2388
|
return join9(home, ".zshrc");
|
|
2362
|
-
if (
|
|
2389
|
+
if (existsSync8(join9(home, ".bashrc")))
|
|
2363
2390
|
return join9(home, ".bashrc");
|
|
2364
2391
|
return null;
|
|
2365
2392
|
}
|
|
2393
|
+
function setupWindows(intervalMinutes) {
|
|
2394
|
+
const runCmd = join9(BIN_DIR, "run.cmd").replace(/\//g, "\\");
|
|
2395
|
+
try {
|
|
2396
|
+
execSync(`schtasks /Delete /TN "${TASK_NAME}" /F`, { stdio: "ignore" });
|
|
2397
|
+
} catch {}
|
|
2398
|
+
execSync(`schtasks /Create /TN "${TASK_NAME}" /TR "${runCmd}" /SC MINUTE /MO ${intervalMinutes} /F`, { stdio: "ignore" });
|
|
2399
|
+
}
|
|
2366
2400
|
function installSync(apiKey, intervalMinutes = 10) {
|
|
2367
2401
|
const messages = [];
|
|
2368
|
-
const os =
|
|
2402
|
+
const os = platform5();
|
|
2369
2403
|
persistBinary(apiKey);
|
|
2370
2404
|
messages.push("Persisted CLI to ~/.conare/bin/");
|
|
2371
2405
|
messages.push("Saved config to ~/.conare/config.json");
|
|
@@ -2376,6 +2410,9 @@ function installSync(apiKey, intervalMinutes = 10) {
|
|
|
2376
2410
|
setupMacOS(intervalMinutes);
|
|
2377
2411
|
messages.push(`Installed launchd agent (every ${intervalMinutes} min)`);
|
|
2378
2412
|
messages.push(`Plist: ${PLIST_PATH}`);
|
|
2413
|
+
} else if (os === "win32") {
|
|
2414
|
+
setupWindows(intervalMinutes);
|
|
2415
|
+
messages.push(`Installed Windows Task Scheduler (every ${intervalMinutes} min)`);
|
|
2379
2416
|
} else if (os === "linux") {
|
|
2380
2417
|
if (hasSystemd()) {
|
|
2381
2418
|
setupLinuxSystemd(intervalMinutes);
|
|
@@ -2391,23 +2428,28 @@ function installSync(apiKey, intervalMinutes = 10) {
|
|
|
2391
2428
|
}
|
|
2392
2429
|
function uninstallSync() {
|
|
2393
2430
|
const messages = [];
|
|
2394
|
-
const os =
|
|
2431
|
+
const os = platform5();
|
|
2395
2432
|
if (os === "darwin") {
|
|
2396
2433
|
try {
|
|
2397
2434
|
execSync(`launchctl bootout gui/${uid()} "${PLIST_PATH}" 2>/dev/null`, { stdio: "ignore" });
|
|
2398
2435
|
} catch {}
|
|
2399
|
-
if (
|
|
2436
|
+
if (existsSync8(PLIST_PATH)) {
|
|
2400
2437
|
unlinkSync(PLIST_PATH);
|
|
2401
2438
|
messages.push("Removed launchd agent");
|
|
2402
2439
|
}
|
|
2440
|
+
} else if (os === "win32") {
|
|
2441
|
+
try {
|
|
2442
|
+
execSync(`schtasks /Delete /TN "${TASK_NAME}" /F`, { stdio: "ignore" });
|
|
2443
|
+
messages.push("Removed Windows scheduled task");
|
|
2444
|
+
} catch {}
|
|
2403
2445
|
} else if (os === "linux") {
|
|
2404
2446
|
if (hasSystemd()) {
|
|
2405
2447
|
try {
|
|
2406
2448
|
execSync("systemctl --user disable --now conare-sync.timer 2>/dev/null", { stdio: "ignore" });
|
|
2407
2449
|
} catch {}
|
|
2408
|
-
if (
|
|
2450
|
+
if (existsSync8(SYSTEMD_SERVICE))
|
|
2409
2451
|
unlinkSync(SYSTEMD_SERVICE);
|
|
2410
|
-
if (
|
|
2452
|
+
if (existsSync8(SYSTEMD_TIMER))
|
|
2411
2453
|
unlinkSync(SYSTEMD_TIMER);
|
|
2412
2454
|
try {
|
|
2413
2455
|
execSync("systemctl --user daemon-reload", { stdio: "ignore" });
|
|
@@ -2430,10 +2472,10 @@ function uninstallSync() {
|
|
|
2430
2472
|
join9(CONARE_DIR, "sync.lock")
|
|
2431
2473
|
];
|
|
2432
2474
|
for (const f of filesToRemove) {
|
|
2433
|
-
if (
|
|
2475
|
+
if (existsSync8(f))
|
|
2434
2476
|
unlinkSync(f);
|
|
2435
2477
|
}
|
|
2436
|
-
if (
|
|
2478
|
+
if (existsSync8(BIN_DIR)) {
|
|
2437
2479
|
rmSync(BIN_DIR, { recursive: true, force: true });
|
|
2438
2480
|
messages.push("Removed ~/.conare/bin/");
|
|
2439
2481
|
}
|
|
@@ -2625,8 +2667,8 @@ async function main() {
|
|
|
2625
2667
|
let configFileKey;
|
|
2626
2668
|
if (opts.configFile) {
|
|
2627
2669
|
try {
|
|
2628
|
-
const { readFileSync:
|
|
2629
|
-
const raw = JSON.parse(
|
|
2670
|
+
const { readFileSync: readFileSync10 } = await import("node:fs");
|
|
2671
|
+
const raw = JSON.parse(readFileSync10(opts.configFile, "utf-8"));
|
|
2630
2672
|
configFileKey = raw.apiKey || raw.key;
|
|
2631
2673
|
if (!configFileKey) {
|
|
2632
2674
|
console.error(`Error: no apiKey/key found in ${opts.configFile}`);
|
|
@@ -2658,7 +2700,7 @@ async function main() {
|
|
|
2658
2700
|
}));
|
|
2659
2701
|
let interactiveMode = false;
|
|
2660
2702
|
if (shouldRunInteractive) {
|
|
2661
|
-
const detectedTools = detect();
|
|
2703
|
+
const detectedTools = await detect();
|
|
2662
2704
|
interactiveTargets = MCP_TARGETS.map((target) => {
|
|
2663
2705
|
const detected = detectedTools.find((tool) => target.id === "claude" && tool.name === "Claude Code" || target.id === "cursor" && tool.name === "Cursor" || target.id === "codex" && tool.name === "Codex" || target.id === "openclaw" && tool.name === "OpenClaw");
|
|
2664
2706
|
return {
|
|
@@ -2718,7 +2760,7 @@ async function main() {
|
|
|
2718
2760
|
log("");
|
|
2719
2761
|
}
|
|
2720
2762
|
}
|
|
2721
|
-
if (!opts.wasmDir &&
|
|
2763
|
+
if (!opts.wasmDir && existsSync9(join10(process.cwd(), "node_modules", "sql.js"))) {
|
|
2722
2764
|
opts.wasmDir = join10(process.cwd(), "node_modules");
|
|
2723
2765
|
}
|
|
2724
2766
|
if (effectiveConfigOnly) {
|
|
@@ -2795,7 +2837,7 @@ Nothing new to index.`);
|
|
|
2795
2837
|
}
|
|
2796
2838
|
log();
|
|
2797
2839
|
}
|
|
2798
|
-
const tools = detect();
|
|
2840
|
+
const tools = await detect();
|
|
2799
2841
|
if (!interactiveMode) {
|
|
2800
2842
|
log("Detected AI tools:");
|
|
2801
2843
|
for (const t of tools) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "conare",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Conare CLI for ingesting AI chat history and configuring memory at conare.ai",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,16 @@
|
|
|
13
13
|
"files": [
|
|
14
14
|
"dist"
|
|
15
15
|
],
|
|
16
|
-
"keywords": [
|
|
16
|
+
"keywords": [
|
|
17
|
+
"conare",
|
|
18
|
+
"ai",
|
|
19
|
+
"memory",
|
|
20
|
+
"mcp",
|
|
21
|
+
"claude",
|
|
22
|
+
"cursor",
|
|
23
|
+
"codex",
|
|
24
|
+
"context"
|
|
25
|
+
],
|
|
17
26
|
"homepage": "https://conare.ai",
|
|
18
27
|
"license": "MIT",
|
|
19
28
|
"dependencies": {
|