conare 0.0.2 → 0.0.4
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 +220 -29
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -3,8 +3,8 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
4
4
|
|
|
5
5
|
// src/index.ts
|
|
6
|
-
import { existsSync as
|
|
7
|
-
import { join as
|
|
6
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
7
|
+
import { join as join9 } from "node:path";
|
|
8
8
|
|
|
9
9
|
// src/detect.ts
|
|
10
10
|
import { existsSync, readdirSync } from "node:fs";
|
|
@@ -887,6 +887,11 @@ import { homedir as homedir5 } from "node:os";
|
|
|
887
887
|
import { spawnSync } from "node:child_process";
|
|
888
888
|
var CONARE_URL = "https://mcp.conare.ai";
|
|
889
889
|
var SERVER_NAME = "conare-memory";
|
|
890
|
+
var MCP_TARGETS = [
|
|
891
|
+
{ id: "claude", label: "Claude Code" },
|
|
892
|
+
{ id: "cursor", label: "Cursor" },
|
|
893
|
+
{ id: "codex", label: "Codex" }
|
|
894
|
+
];
|
|
890
895
|
function readJsonFile(path) {
|
|
891
896
|
try {
|
|
892
897
|
return JSON.parse(readFileSync6(path, "utf-8"));
|
|
@@ -934,19 +939,140 @@ function configureJsonClient(path, apiKey, label) {
|
|
|
934
939
|
upsertMcpServer(path, apiKey);
|
|
935
940
|
return `${label} configured at ${path}`;
|
|
936
941
|
}
|
|
937
|
-
function configureMcp(apiKey) {
|
|
942
|
+
function configureMcp(apiKey, targets = ["claude", "cursor", "codex"]) {
|
|
938
943
|
const results = [];
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
944
|
+
if (targets.includes("claude")) {
|
|
945
|
+
results.push(configureClaude(apiKey));
|
|
946
|
+
}
|
|
947
|
+
if (targets.includes("cursor")) {
|
|
948
|
+
results.push(configureJsonClient(join7(homedir5(), ".cursor", "mcp.json"), apiKey, "Cursor"));
|
|
949
|
+
}
|
|
950
|
+
if (targets.includes("codex")) {
|
|
951
|
+
results.push(configureJsonClient(join7(homedir5(), ".codex", "mcp.json"), apiKey, "Codex"));
|
|
952
|
+
}
|
|
942
953
|
return results;
|
|
943
954
|
}
|
|
944
955
|
|
|
956
|
+
// src/config.ts
|
|
957
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync3 } from "node:fs";
|
|
958
|
+
import { join as join8 } from "node:path";
|
|
959
|
+
import { homedir as homedir6 } from "node:os";
|
|
960
|
+
var CONFIG_DIR = join8(homedir6(), ".conare");
|
|
961
|
+
var CONFIG_PATH = join8(CONFIG_DIR, "config.json");
|
|
962
|
+
function readConfig() {
|
|
963
|
+
try {
|
|
964
|
+
if (!existsSync6(CONFIG_PATH))
|
|
965
|
+
return {};
|
|
966
|
+
return JSON.parse(readFileSync7(CONFIG_PATH, "utf-8"));
|
|
967
|
+
} catch {
|
|
968
|
+
return {};
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
function saveApiKey(apiKey) {
|
|
972
|
+
mkdirSync3(CONFIG_DIR, { recursive: true });
|
|
973
|
+
writeFileSync3(CONFIG_PATH, JSON.stringify({ apiKey }, null, 2) + `
|
|
974
|
+
`);
|
|
975
|
+
}
|
|
976
|
+
function getSavedApiKey() {
|
|
977
|
+
return readConfig().apiKey;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
// src/interactive.ts
|
|
981
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
982
|
+
import { createInterface } from "node:readline/promises";
|
|
983
|
+
function normalizeYesNo(value, defaultValue) {
|
|
984
|
+
const normalized = value.trim().toLowerCase();
|
|
985
|
+
if (!normalized)
|
|
986
|
+
return defaultValue;
|
|
987
|
+
if (["y", "yes"].includes(normalized))
|
|
988
|
+
return true;
|
|
989
|
+
if (["n", "no"].includes(normalized))
|
|
990
|
+
return false;
|
|
991
|
+
return defaultValue;
|
|
992
|
+
}
|
|
993
|
+
async function runInteractiveSetup(options) {
|
|
994
|
+
const rl = createInterface({ input, output });
|
|
995
|
+
try {
|
|
996
|
+
output.write(`
|
|
997
|
+
Conare setup
|
|
998
|
+
|
|
999
|
+
`);
|
|
1000
|
+
let apiKey = options.providedApiKey;
|
|
1001
|
+
if (apiKey) {
|
|
1002
|
+
output.write(`Using API key from --key
|
|
1003
|
+
`);
|
|
1004
|
+
} else {
|
|
1005
|
+
const apiKeyPrompt = options.savedApiKey ? `API key [press enter to use saved key ending in ${options.savedApiKey.slice(-6)}]: ` : "API key: ";
|
|
1006
|
+
const apiKeyAnswer = await rl.question(apiKeyPrompt);
|
|
1007
|
+
apiKey = apiKeyAnswer.trim() || options.savedApiKey;
|
|
1008
|
+
}
|
|
1009
|
+
output.write(`
|
|
1010
|
+
Clients to configure:
|
|
1011
|
+
`);
|
|
1012
|
+
options.detectedTargets.forEach((target, index) => {
|
|
1013
|
+
const availability = target.available === false ? " (not detected locally)" : "";
|
|
1014
|
+
const recommendation = target.recommended ? " [default]" : "";
|
|
1015
|
+
output.write(` ${index + 1}. ${target.label}${recommendation}${availability}
|
|
1016
|
+
`);
|
|
1017
|
+
});
|
|
1018
|
+
const defaultSelection = options.detectedTargets.map((target, index) => target.recommended ? String(index + 1) : null).filter((value) => !!value).join(",");
|
|
1019
|
+
const targetAnswer = await rl.question(`Select clients [${defaultSelection || "none"}]: `);
|
|
1020
|
+
const selectedIndexes = (targetAnswer.trim() || defaultSelection).split(",").map((part) => parseInt(part.trim(), 10)).filter((value) => Number.isFinite(value) && value >= 1 && value <= options.detectedTargets.length);
|
|
1021
|
+
const configureTargets = [...new Set(selectedIndexes)].map((index) => options.detectedTargets[index - 1]?.id).filter((value) => !!value);
|
|
1022
|
+
const ingestChats = normalizeYesNo(await rl.question("Ingest chat history? [Y/n]: "), true);
|
|
1023
|
+
const indexCodebase2 = normalizeYesNo(await rl.question("Index current codebase too? [y/N]: "), false);
|
|
1024
|
+
let indexPath;
|
|
1025
|
+
if (indexCodebase2) {
|
|
1026
|
+
const pathAnswer = await rl.question("Codebase path [.]: ");
|
|
1027
|
+
indexPath = pathAnswer.trim() || ".";
|
|
1028
|
+
}
|
|
1029
|
+
output.write(`
|
|
1030
|
+
`);
|
|
1031
|
+
return {
|
|
1032
|
+
apiKey,
|
|
1033
|
+
configureTargets,
|
|
1034
|
+
ingestChats,
|
|
1035
|
+
indexCodebase: indexCodebase2,
|
|
1036
|
+
indexPath
|
|
1037
|
+
};
|
|
1038
|
+
} finally {
|
|
1039
|
+
rl.close();
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
|
|
945
1043
|
// src/index.ts
|
|
946
1044
|
function getDedupKey(memory) {
|
|
947
1045
|
const metadata = memory.metadata;
|
|
948
1046
|
return metadata?.sessionId || metadata?.fileHash || null;
|
|
949
1047
|
}
|
|
1048
|
+
function printMissingKeyError() {
|
|
1049
|
+
console.error("Error: no API key configured.");
|
|
1050
|
+
console.error("");
|
|
1051
|
+
console.error("Run one of these:");
|
|
1052
|
+
console.error(" bunx conare@latest --key YOUR_API_KEY");
|
|
1053
|
+
console.error(" npx conare@latest --key YOUR_API_KEY");
|
|
1054
|
+
console.error("");
|
|
1055
|
+
console.error("For a built-in command, install globally:");
|
|
1056
|
+
console.error(" bun add -g conare");
|
|
1057
|
+
console.error(" npm i -g conare");
|
|
1058
|
+
console.error("");
|
|
1059
|
+
console.error("Get your API key at https://mcp.conare.ai");
|
|
1060
|
+
}
|
|
1061
|
+
function printFailureSummary(results, memories) {
|
|
1062
|
+
const failures = results.map((result, index) => ({ ...result, memory: memories[index] })).filter((result) => !result.success);
|
|
1063
|
+
if (failures.length === 0)
|
|
1064
|
+
return;
|
|
1065
|
+
console.log("");
|
|
1066
|
+
console.log(" Failure summary:");
|
|
1067
|
+
for (const failure of failures.slice(0, 3)) {
|
|
1068
|
+
const metadata = failure.memory.metadata;
|
|
1069
|
+
const label = metadata?.filePath || metadata?.sessionId || failure.memory.containerTag;
|
|
1070
|
+
console.log(` - ${label}: ${failure.error || "Upload failed"}`);
|
|
1071
|
+
}
|
|
1072
|
+
if (failures.length > 3) {
|
|
1073
|
+
console.log(` - ... and ${failures.length - 3} more`);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
950
1076
|
function parseArgs() {
|
|
951
1077
|
const args = process.argv.slice(2);
|
|
952
1078
|
let key = "";
|
|
@@ -954,6 +1080,7 @@ function parseArgs() {
|
|
|
954
1080
|
let force = false;
|
|
955
1081
|
let ingestOnly = false;
|
|
956
1082
|
let configOnly = false;
|
|
1083
|
+
let interactive = false;
|
|
957
1084
|
let source;
|
|
958
1085
|
let wasmDir;
|
|
959
1086
|
let indexPath;
|
|
@@ -974,6 +1101,8 @@ function parseArgs() {
|
|
|
974
1101
|
ingestOnly = true;
|
|
975
1102
|
} else if (args[i] === "--config-only") {
|
|
976
1103
|
configOnly = true;
|
|
1104
|
+
} else if (args[i] === "--interactive") {
|
|
1105
|
+
interactive = true;
|
|
977
1106
|
} else if (args[i] === "--help" || args[i] === "-h") {
|
|
978
1107
|
console.log(`
|
|
979
1108
|
conare — Ingest AI chat history into Conare
|
|
@@ -989,19 +1118,16 @@ Options:
|
|
|
989
1118
|
--force Re-ingest all / re-index all (bypass dedup)
|
|
990
1119
|
--ingest-only Ingest memories without MCP configuration
|
|
991
1120
|
--config-only Configure MCP only, skip ingestion
|
|
1121
|
+
--interactive Run guided setup prompts
|
|
992
1122
|
--source <name> Only ingest from: claude, codex, cursor
|
|
993
1123
|
--wasm-dir <path> Path to sql.js module (for Cursor ingestion)
|
|
994
1124
|
|
|
995
|
-
Get your API key at https://conare.ai
|
|
1125
|
+
Get your API key at https://mcp.conare.ai
|
|
996
1126
|
`);
|
|
997
1127
|
process.exit(0);
|
|
998
1128
|
}
|
|
999
1129
|
}
|
|
1000
|
-
if (!key) {
|
|
1001
|
-
console.error("Error: --key is required. Get your API key at https://conare.ai");
|
|
1002
|
-
process.exit(1);
|
|
1003
|
-
}
|
|
1004
|
-
if (!key.startsWith("cmem_")) {
|
|
1130
|
+
if (key && !key.startsWith("cmem_")) {
|
|
1005
1131
|
console.error("Error: API key must start with cmem_");
|
|
1006
1132
|
process.exit(1);
|
|
1007
1133
|
}
|
|
@@ -1009,31 +1135,66 @@ Get your API key at https://conare.ai
|
|
|
1009
1135
|
console.error("Error: --ingest-only and --config-only cannot be used together");
|
|
1010
1136
|
process.exit(1);
|
|
1011
1137
|
}
|
|
1012
|
-
return { key, dryRun, force, ingestOnly, configOnly, source, wasmDir, indexPath };
|
|
1138
|
+
return { key, dryRun, force, ingestOnly, configOnly, interactive, source, wasmDir, indexPath };
|
|
1013
1139
|
}
|
|
1014
1140
|
async function main() {
|
|
1015
1141
|
const opts = parseArgs();
|
|
1142
|
+
const savedApiKey = getSavedApiKey();
|
|
1143
|
+
const shouldRunInteractive = !opts.dryRun && !opts.force && !opts.source && !opts.indexPath && !opts.configOnly && !opts.ingestOnly && !opts.wasmDir && !!process.stdin.isTTY && !!process.stdout.isTTY;
|
|
1144
|
+
let selectedTargets = MCP_TARGETS.map((target) => target.id);
|
|
1145
|
+
let effectiveConfigOnly = opts.configOnly;
|
|
1146
|
+
let effectiveIngestOnly = opts.ingestOnly;
|
|
1147
|
+
let effectiveIndexPath = opts.indexPath;
|
|
1148
|
+
let postIngestIndexPath;
|
|
1149
|
+
let apiKey = opts.key || process.env.CONARE_API_KEY || savedApiKey;
|
|
1150
|
+
if (shouldRunInteractive) {
|
|
1151
|
+
const detectedTools = detect();
|
|
1152
|
+
const answers = await runInteractiveSetup({
|
|
1153
|
+
savedApiKey,
|
|
1154
|
+
providedApiKey: opts.key,
|
|
1155
|
+
detectedTargets: MCP_TARGETS.map((target) => {
|
|
1156
|
+
const detected = detectedTools.find((tool) => target.id === "claude" && tool.name === "Claude Code" || target.id === "cursor" && tool.name === "Cursor" || target.id === "codex" && tool.name === "Codex");
|
|
1157
|
+
return {
|
|
1158
|
+
id: target.id,
|
|
1159
|
+
label: target.label,
|
|
1160
|
+
available: detected?.available,
|
|
1161
|
+
recommended: detected?.available !== false
|
|
1162
|
+
};
|
|
1163
|
+
})
|
|
1164
|
+
});
|
|
1165
|
+
apiKey = answers.apiKey || apiKey;
|
|
1166
|
+
selectedTargets = answers.configureTargets.length > 0 ? answers.configureTargets : [];
|
|
1167
|
+
effectiveConfigOnly = !answers.ingestChats && !answers.indexCodebase;
|
|
1168
|
+
effectiveIngestOnly = answers.ingestChats && answers.configureTargets.length === 0;
|
|
1169
|
+
effectiveIndexPath = !answers.ingestChats && answers.indexCodebase ? answers.indexPath || "." : undefined;
|
|
1170
|
+
postIngestIndexPath = answers.ingestChats && answers.indexCodebase ? answers.indexPath || "." : undefined;
|
|
1171
|
+
}
|
|
1172
|
+
if (!apiKey) {
|
|
1173
|
+
printMissingKeyError();
|
|
1174
|
+
process.exit(1);
|
|
1175
|
+
}
|
|
1016
1176
|
console.log("");
|
|
1017
1177
|
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
1018
1178
|
console.log(" Conare Installer");
|
|
1019
1179
|
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
1020
1180
|
console.log("");
|
|
1021
1181
|
process.stdout.write("Validating API key... ");
|
|
1022
|
-
const auth = await validateKey(
|
|
1182
|
+
const auth = await validateKey(apiKey);
|
|
1023
1183
|
if (!auth.valid) {
|
|
1024
|
-
console.error("INVALID. Check your key at https://conare.ai");
|
|
1184
|
+
console.error("INVALID. Check your key at https://mcp.conare.ai");
|
|
1025
1185
|
process.exit(1);
|
|
1026
1186
|
}
|
|
1027
|
-
console.log(`OK (${auth.email})`);
|
|
1187
|
+
console.log(auth.email ? `OK (${auth.email})` : "OK");
|
|
1188
|
+
saveApiKey(apiKey);
|
|
1028
1189
|
console.log();
|
|
1029
|
-
if (!opts.wasmDir &&
|
|
1030
|
-
opts.wasmDir =
|
|
1190
|
+
if (!opts.wasmDir && existsSync7(join9(process.cwd(), "node_modules", "sql.js"))) {
|
|
1191
|
+
opts.wasmDir = join9(process.cwd(), "node_modules");
|
|
1031
1192
|
}
|
|
1032
|
-
if (
|
|
1193
|
+
if (effectiveConfigOnly) {
|
|
1033
1194
|
if (!opts.dryRun) {
|
|
1034
1195
|
console.log("─── Configuring MCP ───");
|
|
1035
1196
|
console.log("");
|
|
1036
|
-
for (const line of configureMcp(
|
|
1197
|
+
for (const line of configureMcp(apiKey, selectedTargets)) {
|
|
1037
1198
|
console.log(` ✓ ${line}`);
|
|
1038
1199
|
}
|
|
1039
1200
|
console.log("");
|
|
@@ -1044,9 +1205,9 @@ async function main() {
|
|
|
1044
1205
|
console.log("");
|
|
1045
1206
|
return;
|
|
1046
1207
|
}
|
|
1047
|
-
if (
|
|
1208
|
+
if (effectiveIndexPath !== undefined) {
|
|
1048
1209
|
const { resolve: resolve2 } = await import("node:path");
|
|
1049
|
-
const absPath = resolve2(
|
|
1210
|
+
const absPath = resolve2(effectiveIndexPath);
|
|
1050
1211
|
console.log(`Indexing codebase: ${absPath}`);
|
|
1051
1212
|
if (opts.force) {
|
|
1052
1213
|
clearIngested("codebase");
|
|
@@ -1054,7 +1215,7 @@ async function main() {
|
|
|
1054
1215
|
try {
|
|
1055
1216
|
await fetch("https://mcp.conare.ai/api/containers/codebase", {
|
|
1056
1217
|
method: "DELETE",
|
|
1057
|
-
headers: { Authorization: `Bearer ${
|
|
1218
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
1058
1219
|
});
|
|
1059
1220
|
console.log("done");
|
|
1060
1221
|
} catch {
|
|
@@ -1078,7 +1239,7 @@ Nothing new to index.`);
|
|
|
1078
1239
|
console.log(` ... and ${memories.length - 10} more`);
|
|
1079
1240
|
} else {
|
|
1080
1241
|
const barWidth = 20;
|
|
1081
|
-
const { success, failed, results } = await uploadBulk(
|
|
1242
|
+
const { success, failed, results } = await uploadBulk(apiKey, memories, (uploaded, total, _failed) => {
|
|
1082
1243
|
const pct = (uploaded / total * 100).toFixed(1);
|
|
1083
1244
|
const filled = Math.round(uploaded / total * barWidth);
|
|
1084
1245
|
const bar = "█".repeat(filled) + "░".repeat(barWidth - filled);
|
|
@@ -1088,12 +1249,13 @@ Nothing new to index.`);
|
|
|
1088
1249
|
`);
|
|
1089
1250
|
const fileHashes = results.filter((result) => result.success).map((result) => getDedupKey(memories[result.index])).filter((key) => !!key);
|
|
1090
1251
|
markIngested("codebase", fileHashes);
|
|
1252
|
+
printFailureSummary(results, memories);
|
|
1091
1253
|
}
|
|
1092
1254
|
console.log();
|
|
1093
|
-
if (!opts.dryRun && !
|
|
1255
|
+
if (!opts.dryRun && !effectiveIngestOnly) {
|
|
1094
1256
|
console.log("─── Configuring MCP ───");
|
|
1095
1257
|
console.log("");
|
|
1096
|
-
for (const line of configureMcp(
|
|
1258
|
+
for (const line of configureMcp(apiKey, selectedTargets)) {
|
|
1097
1259
|
console.log(` ✓ ${line}`);
|
|
1098
1260
|
}
|
|
1099
1261
|
console.log("");
|
|
@@ -1154,7 +1316,7 @@ Nothing new to index.`);
|
|
|
1154
1316
|
console.log(` ... and ${allMemories.length - 5} more`);
|
|
1155
1317
|
} else {
|
|
1156
1318
|
const barWidth = 20;
|
|
1157
|
-
const { success, failed, results } = await uploadBulk(
|
|
1319
|
+
const { success, failed, results } = await uploadBulk(apiKey, allMemories, (uploaded, total, _failed) => {
|
|
1158
1320
|
const pct = (uploaded / total * 100).toFixed(1);
|
|
1159
1321
|
const filled = Math.round(uploaded / total * barWidth);
|
|
1160
1322
|
const bar = "█".repeat(filled) + "░".repeat(barWidth - filled);
|
|
@@ -1165,6 +1327,7 @@ Nothing new to index.`);
|
|
|
1165
1327
|
if (failed > 0) {
|
|
1166
1328
|
console.log(` Re-run with --force to retry failed memories.`);
|
|
1167
1329
|
}
|
|
1330
|
+
printFailureSummary(results, allMemories);
|
|
1168
1331
|
const successfulKeysBySource = {
|
|
1169
1332
|
claude: [],
|
|
1170
1333
|
codex: [],
|
|
@@ -1195,17 +1358,45 @@ Nothing new to index.`);
|
|
|
1195
1358
|
}
|
|
1196
1359
|
}
|
|
1197
1360
|
console.log();
|
|
1198
|
-
if (!opts.dryRun && !
|
|
1361
|
+
if (!opts.dryRun && !effectiveIngestOnly) {
|
|
1199
1362
|
console.log("─── Configuring MCP ───");
|
|
1200
1363
|
console.log("");
|
|
1201
|
-
for (const line of configureMcp(
|
|
1364
|
+
for (const line of configureMcp(apiKey, selectedTargets)) {
|
|
1202
1365
|
console.log(` ✓ ${line}`);
|
|
1203
1366
|
}
|
|
1204
1367
|
console.log("");
|
|
1205
1368
|
}
|
|
1369
|
+
if (postIngestIndexPath) {
|
|
1370
|
+
const { resolve: resolve2 } = await import("node:path");
|
|
1371
|
+
const absPath = resolve2(postIngestIndexPath);
|
|
1372
|
+
console.log("─── Indexing codebase ───");
|
|
1373
|
+
console.log("");
|
|
1374
|
+
process.stdout.write("Scanning files... ");
|
|
1375
|
+
const { memories, fileCount, skipped } = indexCodebase(absPath);
|
|
1376
|
+
console.log(`${fileCount} files found, ${skipped} skipped`);
|
|
1377
|
+
if (memories.length === 0) {
|
|
1378
|
+
console.log(`
|
|
1379
|
+
Nothing new to index.`);
|
|
1380
|
+
} else {
|
|
1381
|
+
const barWidth = 20;
|
|
1382
|
+
const { success, failed, results } = await uploadBulk(apiKey, memories, (uploaded, total, _failed) => {
|
|
1383
|
+
const pct = (uploaded / total * 100).toFixed(1);
|
|
1384
|
+
const filled = Math.round(uploaded / total * barWidth);
|
|
1385
|
+
const bar = "█".repeat(filled) + "░".repeat(barWidth - filled);
|
|
1386
|
+
process.stdout.write(`\r Uploading [\x1B[36m${bar}\x1B[0m] ${uploaded}/${total} (${pct}%)`);
|
|
1387
|
+
});
|
|
1388
|
+
process.stdout.write(`\r \x1B[32m✓\x1B[0m ${success} files indexed, ${failed} failed${" ".repeat(20)}
|
|
1389
|
+
`);
|
|
1390
|
+
const fileHashes = results.filter((result) => result.success).map((result) => getDedupKey(memories[result.index])).filter((key) => !!key);
|
|
1391
|
+
markIngested("codebase", fileHashes);
|
|
1392
|
+
printFailureSummary(results, memories);
|
|
1393
|
+
}
|
|
1394
|
+
console.log("");
|
|
1395
|
+
}
|
|
1206
1396
|
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
1207
1397
|
console.log(" ✓ Done! Every new conversation now starts with context.");
|
|
1208
1398
|
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
1399
|
+
console.log(" Next time you can run `conare` after a global install.");
|
|
1209
1400
|
console.log("");
|
|
1210
1401
|
}
|
|
1211
1402
|
main().catch((e) => {
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "conare",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Conare CLI for ingesting AI chat history and configuring memory at conare.ai",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"conare": "./dist/index.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"build": "bun build src/index.ts --outdir dist --target node --format esm --external sql.js
|
|
10
|
+
"build": "bun build src/index.ts --outdir dist --target node --format esm --external sql.js",
|
|
11
11
|
"prepublishOnly": "bun run build"
|
|
12
12
|
},
|
|
13
13
|
"files": [
|